孝感实诚网络科技有限公司 · 实诚科技 · 湖北孝感

一次列表页从 2.3 秒到 180 毫秒:MySQL 慢查询定位与索引重建全过程

2026-11-04 · 实诚科技 · 孝感实诚网络科技有限公司

问题现象:订单列表页,默认打开 2.3 秒,加筛选条件后 4 秒以上。数据量不大——订单表 18 万行,客户表 2 万行。按理说不该这么慢。 第一步:先确认慢在哪儿 不要猜。先开慢查询日志: SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 0.5; SET GLOBAL log_queries_not_using_indexes = ON; 跑一遍列表页,日志里立刻出现一条 2.1 秒的查询。摘出来看: SELECT o.*, c.name FROM orders o LEFT JOIN customers c ON c.id = o.customer_id WHERE o.status = 1 AND (o.order_no LIKE '%A1024%' OR c.name LIKE '%A1024%' OR c.phone LIKE '%A1024%') ORDER BY o.created_at DESC LIMIT 20 OFFSET 0; 第二步:EXPLAIN 看执行计划 type=ALL rows=180342 Extra=Using where; Using temporary; Using filesort 三个问题同时出现: type=ALL :全表扫描,索引没用上; Using temporary :因为 OR 跨了两张表,优化器只能建临时表; Using filesort :排序也在临时表上做。 根本原因是那句 OR c.name LIKE '%...%' :模糊查询前置通配符本身就用不了索引,再加上跨表 OR,优化器直接放弃索引。 第三步:先改 SQL,再谈索引 思路是把「一个查询干三件事」拆开。用户搜索时其实只需要知道「哪些订单匹配」,可以先查出匹配的客户 ID,再查订单: -- 1) 先查客户 SELECT id FROM customers WHERE name LIKE 'A1024%' OR phone LIKE 'A1024%' LIMIT 500; -- 2) 再查订单 SELECT o.*, c.name FROM orders o LEFT JOIN customers c ON c.id = o.customer_id WHERE o.status = 1 AND (o.order_no LIKE 'A1024%' OR o.customer_id IN (…)) ORDER BY o.created_at DESC LIMIT 20; 注意把 '%A1024%' 改成 'A1024%' 。订单号和手机号都是前缀可搜的,用户输入完整号码或单号时前缀匹配足够;如果一定要支持中间匹配,那就不该走数据库,应该上搜索引擎。 第四步:建对复合索引 订单表的查询模式是「按状态过滤 + 按时间排序」,所以索引顺序必须是「等值条件在前,排序字段在后」: ALTER TABLE orders ADD INDEX idx_status_created (status, created_at); ALTER TABLE customers ADD INDEX idx_phone (phone); ALTER TABLE customers ADD INDEX idx_name (name); 为什么不是 (created_at, status) ?因为 status 是等值条件,放在前面能先缩小范围,后面的 created_at 天然有序,可以直接避免 filesort。 第五步:验证,别只看「感觉快了」 type=ref rows=1240 Extra=Using index condition 默认列表:2.3s → 180ms; 带单号搜索:4.1s → 210ms; 带客户名搜索:4.4s → 340ms(多一次客户表查询,可接受)。 持续观察一周,慢查询日志里这条 SQL 不再出现。 几个容易踩的坑 索引不是越多越好 :这张表原来有 6 个单列索引,写操作明显偏慢。加复合索引后删掉了 3 个没用的单列索引。 LIMIT OFFSET 深翻页 :翻到第 500 页时 OFFSET 9980 仍然慢。改用游标分页( WHERE created_at < ? )解决。 COUNT(*) 才是隐藏杀手 :列表页底部要显示总数,18 万行的 COUNT 要 400ms。改成缓存总数、只在筛选条件变化时重算。 别在索引列上用函数 : DATE(created_at) = '2026-11-01' 会让索引失效,改成范围查询。 结论 慢查询优化的顺序应该是:看日志 → EXPLAIN → 改 SQL → 加索引 → 验证。直接加索引往往治标不治本,尤其是遇到 OR、函数、前置通配符这几种写法时,索引根本不会被使用。

孝感实诚网络科技有限公司(实诚科技)专注网站建设、小程序开发、管理系统定制与软件工具开发,咨询热线 13622369854。

新闻资讯列表联系我们
孝感实诚网络科技有限公司 · 咨询热线 13622369854 · 微信 Ae77056 · 邮箱 admin@shichenkeji.com
湖北省孝感市孝南区城站路泰阳城

孝感实诚网络科技有限公司(实诚科技 · 实诚网络)

孝感实诚网络科技有限公司(品牌简称「实诚科技」、「实诚网络」,官网 shichenkeji.com)位于湖北省孝感市孝南区,是一家专注企业数字化服务的技术公司。核心团队平均 8 年以上开发经验,10 年技术沉淀,已为 600+ 家企业提供服务,累计交付 1200+ 项目。

主营业务

联系方式

关于实诚科技 · 自研产品 · 网站模板 · 项目案例 · 新闻资讯 · 联系我们