当前位置: 当前位置:首页 > 热点 > sql优化的方法及思路正文

sql优化的方法及思路

作者:焦点 来源:百科 浏览: 【大 中 小】 发布时间:2026-10-17 06:07:04 评论数:

上个月我接手了一个报表接口,及思单次查询要跑4.8秒。及思数据库里就200万行订单数据,及思索引该建的及思都建了,可它还是及思慢。后来我把SQL拆开看,及思发现罪魁祸首是及思SELECT *带出来37个字段,而前端只需要其中5个。及思就这么一个改动,及思查询时间降到了0.9秒。及思

这就是及思SQL优化的第一原则:别拿数据搬家当查询用。很多人写SQL习惯性SELECT *,及思觉得省事。及思可数据库引擎得把整行数据从磁盘读进内存,及思再通过网络传出去。及思你不需要的字段,白白消耗了IO和带宽。更麻烦的是,如果表上有联合索引,SELECT *会让优化器放弃索引覆盖扫描,老老实实回表查——这一下性能差距能到十倍。

再说说索引。索引不是越多越好,而是越精准越好。我见过一张表上挂了12个索引,每个字段都有。写入慢不说,查询也没快多少。真正的优化思路是:找出那些高频查询的WHERE条件,给它们建联合索引,顺序按等值条件在前、范围条件在后。比如WHERE status = 1 AND create_time > '2024-01-01',联合索引应该建(status, create_time)。你要是反过来建,范围查询后面的等值条件就用不上索引了。

但索引也不是万能药。有时候你发现明明走了索引,还是慢。这时候得看EXPLAIN里的rows字段——如果预估扫描行数还在几十万以上,说明索引选择性太差。比如在性别字段上建索引,扫描一半数据跟全表扫没什么区别。这种情况,不如让优化器直接全表扫,省得来回跳转。

还有一个经常被忽略的点:LIMIT深分页。业务方要导出第100万页的数据,每页20条。LIMIT 20000000, 20这个写法,数据库得先扫2000万行,再扔掉前19999980条。我处理过一个真实案例,线上这个查询跑了38秒,DBA直接报警。改成WHERE id > 上一页最大id LIMIT 20之后,耗时降到0.05秒。这就是利用主键的有序性做游标分页——前提是ID得是自增的,或者你有别的单调递增字段。

写SQL时还有个隐形杀手——隐式类型转换。用户传了个字符串类型的订单号,你拿它跟BIGINT类型的字段比较,MySQL会放弃索引,把每一行都转成字符串再比。这坑我踩过不止一次。解决办法很简单:参数类型跟字段类型保持一致,或者用CAST显式转换。

子查询和JOIN的选择也值得说道。MySQL 8.0之前的版本,子查询优化做得不好,往往会把相关子查询变成逐行执行。换成JOIN之后性能立竿见影。但JOIN也不能瞎用,驱动表要选小表,被驱动表的连接字段要有索引。如果是大表关联大表,那就得考虑冗余字段或者汇总表了。

最后说个反直觉的:有时候SQL优化根本不在SQL本身。我优化过一个接口,SQL都快到极限了,可整体响应还是慢。后来发现是应用层每次查询都新建数据库连接。改成连接池复用之后,响应时间从2秒降到0.3秒。SQL是手段,业务场景才是目的。你优化的目标应该是整个数据链路,不是那一行语句。

优化SQL这事,说到底是跟数据分布和引擎实现博弈。没有银弹,只有一条路:先慢查询日志定位问题SQL,再EXPLAIN看执行计划,然后针对性地调整写法或索引。每一步都得有数据支撑,别凭感觉拍脑袋。改完记得压测,因为统计信息会变,执行计划也会跟着变——你今天优化的结论,可能下个月就失效了。