MySQL查询耗时从10分钟降到秒级是数据库性能优化中常见的需求,这类优化需要结合查询场景、表结构、数据量等多维度分析,找到瓶颈后针对性调整即可实现性能跃升。

第一步:定位慢查询的核心问题
首先需要确认查询耗时的具体原因,避免盲目优化。可以通过开启MySQL慢查询日志,记录执行时间超过阈值的SQL,再结合EXPLAIN命令分析执行计划。
使用如下命令开启慢查询日志:
-- 开启慢查询日志 SET GLOBAL slow_query_log = 'ON'; -- 设置慢查询阈值,单位秒,这里设置为1秒 SET GLOBAL long_query_time = 1; -- 查看慢查询日志文件路径 SHOW VARIABLES LIKE 'slow_query_log_file';
拿到慢查询SQL后,使用EXPLAIN分析执行计划,重点关注type、key、rows、Extra这几个字段:
type如果是ALL表示全表扫描,是性能差的典型表现key为NULL说明没有使用索引rows数值越大,说明扫描的行数越多,耗时越长Extra出现Using filesort、Using temporary说明存在额外排序或临时表操作,也会拖慢查询
第二步:索引优化是核心手段
大部分分钟级慢查询都是因为缺少合适的索引导致全表扫描,需要根据查询条件创建联合索引,遵循最左前缀匹配原则。
假设存在如下用户订单表,数据量达到千万级,原查询SQL耗时10分钟:
SELECT order_id, user_id, order_amount, create_time FROM user_order WHERE user_id = 12345 AND create_time >= '2024-01-01' AND create_time <= '2024-01-31' AND order_status = 2 ORDER BY create_time DESC LIMIT 20;
原表没有针对查询条件的索引,执行计划显示type为ALL,扫描全表千万行数据。根据查询条件,创建联合索引:
-- 创建联合索引,顺序遵循最左前缀:等值条件在前,范围条件在后 CREATE INDEX idx_user_status_time ON user_order(user_id, order_status, create_time);
索引创建后,再次执行EXPLAIN分析,type会变为range,key显示使用了新创建的索引,扫描行数从千万级降到几十行,查询耗时直接降到几百毫秒。
第三步:优化SQL语句写法
部分查询即使有索引,写法不合理也会导致索引失效,常见问题及优化方式如下:
避免对索引字段做函数操作
如果查询条件中对索引字段使用函数,比如WHERE DATE(create_time) = '2024-01-01',会导致索引失效,全表扫描。优化为范围查询:
-- 优化前,索引失效 SELECT * FROM user_order WHERE DATE(create_time) = '2024-01-01'; -- 优化后,索引生效 SELECT * FROM user_order WHERE create_time >= '2024-01-01 00:00:00' AND create_time <= '2024-01-01 23:59:59';
减少不必要的字段查询
避免使用SELECT *,只查询需要的字段,减少数据返回量,同时如果查询字段都在索引中,还可以触发索引覆盖,不需要回表查询数据,进一步提升性能。
优化分页查询
深度分页比如LIMIT 100000, 20会扫描前10万行数据再取20行,耗时很长。可以改为基于上次查询的最后一条记录ID分页:
-- 优化前,深度分页慢 SELECT id, order_amount FROM user_order ORDER BY id LIMIT 100000, 20; -- 优化后,基于上次最大ID查询 SELECT id, order_amount FROM user_order WHERE id > 100000 ORDER BY id LIMIT 20;
第四步:其他辅助优化手段
如果索引和SQL优化后仍有性能问题,可以考虑以下方式:
- 对大表进行分区,按照时间或者业务维度拆分数据,查询时只扫描对应分区
- 定期清理无用数据,减少表的总数据量
- 如果是统计类查询,可以提前汇总数据到汇总表,查询时直接查汇总表
- 调整MySQL配置参数,比如增大
innodb_buffer_pool_size,让更多数据和索引缓存在内存中
通过以上步骤,原本耗时10分钟的查询基本都可以优化到秒级甚至毫秒级,实际优化时需要根据具体场景组合使用多种方法,持续优化迭代即可。