能,但仅对非预处理的SELECT语句生效;重写发生在解析后、优化前,通过正则匹配替换AST中的SELECT子句,不支持DML、存储过程及动态拼接SQL。
MySQL 8.0+ 重写插件是否真能改第三方系统的慢 SQL?
能,但只对
语句生效,且必须走查询解析器(即不能是预处理语句绑定后动态拼的 SQL)。重写插件本质是在 SQL 解析后、优化器开始前,用正则匹配并替换 AST 中的
子句——它不碰
、
、
,也不改存储过程或触发器里的 SQL。
常见误判点:以为开启插件就能“自动加速所有慢查”,结果发现
里耗时没变。原因往往是第三方系统用
+
方式执行 SQL,而重写插件默认不处理这类语句(需显式设置
并确认
中的
表未被绕过)。
怎么写一条安全有效的重写规则?
核心原则:只重写明确可推导、无副作用的子查询或 JOIN 条件。比如把
改成基于具体日期的常量,避免每次执行都调用
导致索引失效。
必须用
注册,不能直接 INSERT 到
匹配模式(
)要加锚点:
,否则可能误伤其他语句
替换内容(
)里禁止含变量、函数或子查询;只允许字面值、列名、表别名和固定 JOIN 条件
规则启用后需执行
,否则不生效
为什么规则加了却没触发?排查三步法
最常卡在权限、作用域和语法细节上:
执行
,确认
是
,且
字段没被截断(MySQL 8.0.22 前该字段长度仅 2048 字符)
检查目标 SQL 是否带 schema 名:如果原语句是
,但规则里写的
,就不会匹配——得写全
并转义点号
用
对比改写前后执行计划,若输出中仍有
或
,说明重写未成功或新 SQL 本身仍不优
重写规则上线后要注意哪些隐性成本?
每条规则都会增加 parser 阶段开销,尤其当
表里规则数 > 50 条时,简单
的解析延迟可能从 0.02ms 升到 0.15ms。更关键的是:规则一旦匹配,原始 SQL 的
、
等 hint 全部丢失,且无法回溯原始语句用于审计。
真实踩坑案例:某系统把
重写为
(漏掉另一状态),上线后订单漏查——因为开发只验证了“有结果”,没验证“结果全不全”。重写不是兜底方案,它只适合逻辑确定、变更可控的局部优化。
SELECTSELECTINSERTUPDATEDELETESHOW PROFILESPREPAREEXECUTEquery_rewrite_enabled=ONperformance_schemaprepared_statements_instancesWHERE create_time > DATE_SUB(NOW(), INTERVAL 7 DAY)NOW()mysql_query_rewrite.add_rewrite_rule()query_rewrite.rewrite_rulespattern^SELECT.*FROM orders WHERE create_time > DATE_SUB\(NOW\(\), INTERVAL 7 DAY\)$replacementmysql_query_rewrite.flush_rewrite_rules()SELECT * FROM performance_schema.query_rewrite_rulesactiveYESpatternSELECT * FROM mydb.ordersFROM ordersFROM mydb\.ordersEXPLAIN FORMAT=TREEDEPENDENT SUBQUERYUsing temporary; Using filesortquery_rewrite_rulesSELECTSQL_NO_CACHESTRAIGHT_JOINWHERE status IN ('pending','processing')WHERE status = 'pending'