MySQL慢SQL查询优化求助:查询25条数据耗时5秒
针对你遇到的这个查询性能问题,我结合你的表结构和现有配置,整理了几个关键优化方向,应该能大幅提升查询速度:
1. 调整索引策略,创建针对性的联合索引
你现有的table1(id,custom_type,confirmation_number)索引顺序不合理——因为你的查询首先需要过滤custom_type = 0的行,再关联table2的transaction_id。MySQL的索引遵循最左前缀匹配原则,所以应该把过滤条件字段放在索引最前面:
CREATE INDEX idx_table1_custom_type_id ON table1(custom_type, id);
这个索引可以让MySQL快速定位到所有custom_type=0的行,然后直接用id去匹配table2的transaction_id,避免全表扫描。
同时,确认table2的transaction_id索引是独立的(你已经创建了),这个索引会让关联查询的效率大幅提升。
2. 改写查询语句,用NOT EXISTS替代LEFT JOIN + IS NULL
你的原查询用LEFT JOIN后判断NULL的方式,在大表场景下效率较低——MySQL需要先完成全量关联,再过滤掉匹配的行。换成NOT EXISTS会更高效,因为它找到第一条匹配的记录后就会停止扫描,不需要遍历整个table2:
SELECT t.* FROM table1 t WHERE t.custom_type = 0 AND NOT EXISTS ( SELECT 1 FROM table2 t2 WHERE t2.transaction_id = t.id ) LIMIT 25;
如果业务允许,尽量不要用SELECT *,只查询你需要的字段——这样不仅减少数据传输量,还能让MySQL尝试使用覆盖索引(如果索引包含所有需要的字段),进一步提速。
3. 用EXPLAIN分析执行计划,验证索引是否生效
执行以下命令查看查询的执行路径:
EXPLAIN SELECT t.* FROM table1 t WHERE t.custom_type = 0 AND NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.transaction_id = t.id) LIMIT 25;
重点关注这几个字段:
type:理想状态是ref或range,如果是ALL说明还是全表扫描,需要检查索引是否正确创建或是否存在隐式类型转换(你的id和transaction_id都是int,类型一致,应该没问题)。key:应该显示我们创建的idx_table1_custom_type_id,以及table2的transaction_id索引。rows:这个数值代表MySQL预估要扫描的行数,数值越小越好。
4. 可选:考虑分区表优化(针对超大表)
如果你的table1和table2数据时间跨度很大(比如按月份累积),可以尝试按date_time字段做分区(比如按月分区)。这样查询时MySQL只会扫描符合条件的分区,避免扫描整个1000万行的表。不过这个操作需要修改表结构,建议先在测试环境验证效果。
通过以上几步优化,你的查询执行时间应该能轻松降到100ms以内。
内容的提问来源于stack exchange,提问作者Xcoder

