首页/数据/SQL 速查/MySQL 8.0 优化器提示 /*+ */
性能与执行计划72 条

MySQL 8.0 优化器提示 /*+ */

语句级提示:INDEX/NO_INDEX 控制索引、JOIN_ORDER 固定连接顺序、SET_VAR 临时改会话变量、MAX_EXECUTION_TIME 限制执行时长。

SQL 速查数据更新于 2026-10-13

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 里更合适。
多个提示同时出现时要注意相互影响:不同提示的作用对象与优先级不同,混用后效果可能与预期不符,逐个加、逐个验证最稳妥。

易错点

  • 把 SET_VAR 当持久设置:只在语句执行期间覆盖,结束后恢复原值,别指望它影响后续语句
  • 提示写了却不生效:需要名称拼写正确、位置正确且版本支持,用 EXPLAIN 验证
  • 用 JOIN_ORDER 长期固定连接顺序:数据分布变化后固定顺序可能不再是好选择
  • 把 MAX_EXECUTION_TIME 用到写入语句上:它只对只读 SELECT 生效
  • 提示与表级提示混用且冲突:两类提示的优先级与作用范围不同,最终计划可能与直觉相反

数据来源与参考

  • MySQL 8.0 Reference Manual · Optimizer Hints
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌