跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

MySQL如何利用重写插件解决第三方系统慢SQL_Query Rewrite配置

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

相关文章