MySQL 服务端支持重写语句功能。你可以认为这类似用正则表达式去匹配特定的语句并重写。
这个功能的设计目标之一是让 DBA 们能够在语句中插入查询提示。这缓和了应用自身无法修改语句的情形,例如用到了 ORM 框架,或应用是私有的。
需要指出的是,说查询重写类似于正则表达式,其实比正则高效得多。当语句被分析时,预编译语句会与内部的需要重写的语句哈希表对照检查。如果一个语句需要重写,服务端会重复这一步骤并重新解析该查询。这意味着不需要重写的语句的处理代价很低,并且需要重写的语句需要解析两次。
例子33:服务端通过重写,改变了查询
# 在命令行中,安装查询重写插件
mysql -u root -p < install_rewriter.sql
-- 在 MySQL 中添加重写规则并应用
INSERT INTO query_rewrite.rewrite_rules(pattern_database, pattern, replacement) VALUES (
"world",
"SELECT * FROM Country WHERE population > ? AND continent=?",
"SELECT * FROM Country WHERE population > ? AND continent=? LIMIT 1"
);
CALL query_rewrite.flush_rewrite_rules();
-- 每次当重写事件发生时,会触发警告信息
SELECT * FROM Country WHERE population > 5000000 AND continent='Asia';
-- 从警告信息可以看到重写结果
SHOW WARNINGS;
Query 'SELECT * FROM Country WHERE population > 5000000 AND continent='Asia''
rewritten to 'SELECT * FROM Country WHERE population > 5000000 AND continent='Asia' LIMIT 1' by a query rewrite plugin
-- 查询重写规则
SELECT * FROM query_rewrite.rewrite_rules
*************************** 1. row ***************************
id: 2
pattern: SELECT * FROM Country WHERE population > ? AND continent=?
pattern_database: world
replacement: SELECT * FROM Country WHERE population > ? AND continent=? LIMIT 1
enabled: YES
message: NULL
pattern_digest: 88876bbb502cef6efddcc661cce77deb
normalized_pattern: select `*` from `world`.`Country` where ((`population` > ?) and (`continent` = ?))
提示
MySQL 服务端支持查询重写插件。这里展示的例子是一个后置解析重写插件(Rewriter),某些查询可能需要一个前置解析插件。更多信息可以在 MySQL 官方手册中找到:
https://dev.mysql.com/doc/refman/5.7/en/rewriter-query-rewrite-plugin.html
译自:
Query Rewrite – The Unofficial MySQL 8.0 Optimizer Guide