SQL查询优化和索引策略是Linux数据库性能提升最直接、见效最快的两个抓手,需结合EXPLAIN分析执行计划、合理创建覆盖索引、优先重写低效SQL,并协同调优Linux内核参数与文件系统配置。
SQL查询优化和索引策略是Linux数据库性能提升最直接、见效最快的两个抓手。不合理的查询写法和缺失/低效的索引,往往让CPU、I/O和内存白白承压,而这些问题在高并发或数据量增长后会集中爆发。关键不在堆硬件,而在看清执行路径、理解数据分布、精准干预访问方式。
看懂EXPLAIN:从执行计划里找瓶颈
优化前不看EXPLAIN,等于蒙眼调参。在MySQL或PostgreSQL中,用EXPLAIN ANALYZE(PostgreSQL)或EXPLAIN FORMAT=JSON(MySQL 8.0+)获取真实执行细节,重点关注:
-
Type字段:ALL(全表扫描)、index(全索引扫描)是危险信号;尽量落到range、ref、eq_ref甚至const
-
Rows/estimated_rows:预估扫描行数远大于实际返回行数?说明索引没走对,或统计信息过期(可运行ANALYZE TABLE更新)
-
Extra列:出现Using filesort、Using temporary、Using join buffer,意味着排序、临时表或缓冲区操作——这些极易成为慢点
-
Key/Actual startup time:确认是否命中预期索引;PostgreSQL中startup time显著高于total time,可能表示过滤条件太弱、索引选择率差
索引不是越多越好:建什么、怎么建、何时删
索引本质是空间换时间,但维护成本(INSERT/UPDATE/DELETE变慢、磁盘占用、缓冲池压力)必须纳入权衡。实战中坚持三条铁律:
-
覆盖索引优先:把SELECT字段和WHERE/ORDER BY/GROUP BY涉及的列打包进一个索引,避免回表。例如SELECT name, status FROM users WHERE dept_id = ? ORDER BY created_at DESC,可建(dept_id, created_at DESC, name, status)
-
区分度高的列放前面:比如gender(只有M/F)和user_id(唯一)组合索引,user_id必须在前,否则索引几乎无效
-
定期清理无用索引:MySQL可通过sys.schema_unused_indexes视图,PostgreSQL查pg_stat_all_indexes中idx_scan为0且存在半年以上的索引,结合慢日志交叉验证
查询重写比加索引更治本的5种情况
很多慢查询根源在逻辑本身。与其硬扛索引,不如先重构SQL:
- 用EXISTS替代IN (子查询),尤其子查询结果集大时,EXISTS可短路退出
- 避免SELECT *,只取必要字段——减少网络传输、避免大字段拖累缓冲池
- 拆分复杂JOIN:单次查10张表不如分2–3次查核心关联,用应用层组装,可控性更强
- 日期范围慎用函数包裹字段:WHERE DATE(create_time) = '2025-01-01'无法走索引,改写为WHERE create_time >= '2025-01-01' AND create_time
- 分页深翻用游标替代OFFSET:LIMIT 10000, 20极慢,改用WHERE id > last_seen_id ORDER BY id LIMIT 20
Linux环境下的协同调优要点
数据库跑在Linux上,内核参数和文件系统行为直接影响IO效率:
- 确保vm.swappiness=1(避免数据库内存被swap),transparent_hugepage=never(防止THP导致锁竞争)
- 数据库数据目录挂载时
启用noatime,nodiratime,减少元数据更新开销
- 使用XFS文件系统(优于ext4对大文件顺序读写的处理),并配置logbsize=256k提升日志写入吞吐
- 监控iostat -x 1中的%util接近100%且await持续偏高,说明磁盘已成瓶颈,需检查SQL是否引发大量随机IO(如未走索引的ORDER BY)