mysql查询慢的主因是where字段无索引导致全表扫描,应建普通或联合索引;like '%xxx'使索引失效,需改用'xxx%'或全文索引;避免select*、n+1查询及order by/group by无索引。

WHERE 条件字段没加索引,查得慢是必然的
MySQL 在执行 SELECT 时,如果 WHERE 中的字段没索引,就会全表扫描。哪怕只有几千行,有 JOIN 或 ORDER BY 时响应也会明显卡顿。
实操建议:
- 用
EXPLAIN SELECT ...看type是否为ALL(全表扫描),key列是否为NULL - 对高频查询条件字段建普通索引,例如用户登录查
username或email,就执行:ALTER TABLE `users` ADD INDEX idx_username (`username`);
- 复合查询优先建联合索引,比如常查
status = 1 AND created_at > '2024-01-01',建INDEX idx_status_created (status, created_at),顺序不能颠倒——等值条件字段放前面,范围条件放后面
PHP 中拼接 SQL 时用了 LIKE '%xxx',索引直接失效
前导通配符(如 LIKE '%abc')会让 MySQL 放弃使用索引,哪怕字段本身有索引。
常见场景:搜索框模糊匹配用户昵称、商品标题。
立即学习“PHP免费学习笔记(深入)”;
解决方向:
- 改用
LIKE 'abc%'(后缀通配),索引仍可生效 - 需要前后模糊?考虑引入
fulltext索引 +MATCH ... AGAINST,但仅限MyISAM或InnoDB(5.6+),且需调整最小词长 - 更重的搜索需求(如高亮、拼音、分词),别硬扛在 MySQL 里,换
Elasticsearch或Sphinx
PHP 查询中用了 SELECT *,IO 和网络开销白增一倍
尤其当表有 TEXT、BLOB 字段,或 JOIN 多张宽表时,SELECT * 会把不需要的字段也从磁盘读出、经网络传给 PHP,既拖慢 MySQL,又加重 PHP 内存压力。
正确做法:
- 明确写出需要的字段,例如:
SELECT id, title, status FROM posts WHERE ... - 避免在循环里查同一条记录多次(N+1 问题),用
JOIN或一次性IN查询预加载,比如查 10 篇文章的作者名,别 for 循环 10 次SELECT name FROM users WHERE id = ? - 大字段(如
content)单独拆表或延迟加载,主列表页不查,详情页再按需SELECT content FROM posts_ext WHERE post_id = ?
ORDER BY 和 GROUP BY 没走索引,临时表+文件排序拖垮性能
当 ORDER BY 字段没索引,或和 WHERE 条件不构成最左前缀时,MySQL 会创建 Using filesort;GROUP BY 同理,可能触发 Using temporary —— 这两种都意味着额外磁盘 IO 和内存消耗。
检查与优化:
- 在
EXPLAIN输出里看Extra列是否含Using filesort或Using temporary -
ORDER BY a, b要走索引,就得有INDEX(a, b);如果还带WHERE c = ?,那联合索引得是INDEX(c, a, b)才能覆盖 - 避免在排序字段上用函数,例如
ORDER BY UPPER(name)会让索引失效;如必须大小写不敏感,建生成列索引:ALTER TABLE users ADD COLUMN name_lower VARCHAR(255) STORED AS (LOWER(name)); CREATE INDEX idx_name_lower ON users(name_lower);
INSERT/UPDATE;真正关键的是理解查询模式,再用 EXPLAIN 验证每条慢 SQL 的执行路径。很多“慢”其实发生在 PHP 层没复用 PDO 预处理、或一次查了 500 行却只显示 10 条这种地方。











