技术博客:MySQL索引优化实战临汾千万级数据查询提速指南
一个真实的性能危机
临汾某农产品电商平台在运营两年后积累了超过1200万条订单数据随着数据量增长越来越多的查询开始变慢——"订单列表页加载要8秒""运营报表跑出来要3分钟""库存查询经常超时"。客户投诉不断技术团队压力巨大。经过排查发现问题的根源在于数据库索引设计不合理——很多高频查询走了全表扫描。本文将以这个真实案例为主线讲解MySQL索引优化的完整方法论。
第一步:找到慢查询
首先开启MySQL的慢查询日志(slow_query_log=ON long_query_time=1)记录执行时间超过1秒的查询。运行一周后使用pt-query-digest工具分析慢日志找出TOP10慢SQL。在本案例中发现以下几类典型慢查询:① 按用户ID+时间范围查订单列表(耗时5-8秒)② 按商品ID统计月度销量(耗时10-30秒)③ 多条件筛选订单(按状态+支付方式+时间范围)(耗时3-15秒)。
第二步:EXPLAIN分析执行计划
对每条慢SQL执行EXPLAIN查看执行计划重点关注type/key/rows/Extra四列。type列表示访问类型(从好到差:const > eq_ref > ref > range > index > ALL)如果出现ALL说明走了全表扫描必须优化。key列显示实际使用的索引如果为NULL说明没用上索引。rows列预估扫描行数越大越慢。Extra列中的"Using filesort""Using temporary"都是危险信号。
第三步:设计与优化索引
场景一:订单列表查询:SQL为SELECT * FROM orders WHERE user_id=? AND create_time BETWEEN ? AND ? ORDER BY create_time DESC LIMIT 20。优化方案:创建联合索引CREATE INDEX idx_user_time ON orders(user_id, create_time DESC)。遵循最左前缀原则user_id在前因为它是等值查询条件create_time在后用于排序。优化后type从ALL变为ref rows从数百万降到几十查询时间从8秒降至0.02秒提升400倍!
场景二:商品销量统计:SQL为SELECT product_id, SUM(quantity) AS total_qty FROM order_items WHERE create_time BETWEEN ? AND ? GROUP BY product_id ORDER BY total_qty DESC LIMIT 50。优化方案:在order_items表的create_time字段创建索引(用于范围扫描)同时在product_id字段创建索引(用于GROUP BY)。更进一步使用覆盖索引避免回表:CREATE INDEX idx_product_qty ON order_items(product_id, quantity, create_time)——注意这里把查询需要的字段都放入索引中使Extra中出现"Using index"表示覆盖索引无需回表查询速度再提升50%。