MySQL 8.0 优化器提示
MySQL 8.0 的优化器提示写在语句里的 /*+ ... */ 注释中:可以控制索引选择、固定连接顺序、临时修改会话变量、限制执行时长。它比表级的 USE/FORCE INDEX 表达力更强,但也同样属于「影响优化器判断」的手段,需要验证是否真的被采纳。
基本信息
| 位置 | 写在 SELECT/UPDATE/DELETE/INSERT 等关键字之后 |
|---|---|
| INDEX / NO_INDEX | 指定某张表使用或排除哪些索引 |
| JOIN_ORDER | 固定多表连接的顺序 |
| SET_VAR | 语句级临时覆盖系统变量 |
| MAX_EXECUTION_TIME | 单位毫秒,只作用于只读 SELECT |
典型使用场景
- 固定多表连接顺序做对比实验
- 临时排除某个索引验证假设
- 给报表查询加上执行时长上限
- 语句级调整排序缓冲区等参数
- 验证新索引能否被优化器选中
示例
示例
-- 固定连接顺序并排除某个索引
SELECT /*+ JOIN_ORDER(u, o), NO_INDEX(o idx_status) */
u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE u.city = 'shanghai';
-- 给报表查询设置执行时长上限(毫秒)
SELECT /*+ MAX_EXECUTION_TIME(1000) */ COUNT(*)
FROM orders;
-- 语句级临时调大排序缓冲区
SELECT /*+ SET_VAR(sort_buffer_size = 32M) */ *
FROM orders ORDER BY total DESC LIMIT 10;常用提示一览
| 提示 | 作用 | 注意 |
|---|---|---|
| INDEX / NO_INDEX | 指定使用或排除索引 | 索引名要拼写正确 |
| JOIN_ORDER / JOIN_PREFIX | 固定连接顺序或前缀 | 数据分布变化后可能变差 |
| SET_VAR | 语句级覆盖系统变量 | 执行完即恢复原值 |
| MAX_EXECUTION_TIME | 限制只读语句时长 | 单位毫秒,只对 SELECT 生效 |
| 生效范围 | 只影响当前语句 | 需用 EXPLAIN 验证是否被采纳 |
提示不生效通常有三类原因:名称拼写错误、位置放错(必须紧跟命令关键字)、或提示之间互相冲突。用 EXPLAIN 看计划是否按预期变化最直接。
SET_VAR 只在语句执行期间覆盖变量,执行结束就恢复:它适合单次语句调优,不能当成会话或全局配置来用。
提示不适合写进通用框架或 ORM 配置:它们与具体版本、索引名强绑定,升级或调整索引后会失效,放在明确标注的报表 SQL 里更合适。
多个提示同时出现时要注意相互影响:不同提示的作用对象与优先级不同,混用后效果可能与预期不符,逐个加、逐个验证最稳妥。