首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Rewrite插件深度指南:不修改代码也能优化慢SQL的终极方案

Rewrite插件深度指南:不修改代码也能优化慢SQL的终极方案

原创
作者头像
小明互联网技术分享社区
发布2025-08-21 10:05:15
发布2025-08-21 10:05:15
32400
代码可运行
举报
文章被收录于专栏:MYSQLMYSQL
运行总次数:0
代码可运行

当SQL成为性能瓶颈时,如何解决?

在数据库优化的战场上,慢SQL如同潜伏的“性能杀手”,轻则导致查询卡顿,重则引发系统雪崩。传统优化依赖人工分析执行计划、添加索引、重构语句,但面对海量SQL和复杂业务,DBA常陷入“救火队长”的困境。 有没有更好的办法解决这个问题呢?

MySQL Rewrite插件技术可以帮我们轻松解决这个问题。通过该技术可以实时拦截低效SQL并自动改写,无需修改业务代码即可实现性能提升。今天分享五个非常实用的实战案例,给大家介绍Rewrite插件的用法,希望对开发的朋友提供一些帮助!

一、Rewrite插件核心原理与配置

1.1 插件工作原理

MySQL Rewrite插件(mysql 5.7.6 及之后的版本)通过解析SQL语法树,匹配预定义的规则模板,动态修改查询结构。例如:

  • 自动补全索引提示:为缺失索引的查询添加FORCE INDEX
  • 隐式转换修正:将WHERE id= '123'改为WHERE id=123
  • 分页重写:将深分页查询转换为延迟关联

说明:MySQL 5.7 的 Query Rewrite Plugin 只支持 SELECT ,在 8.0 里面会支持 INSERT , UPDATE , DELETE

1.2 安装与基础配置示例

代码语言:javascript
代码运行次数:0
运行
复制
-- 安装插件(以MySQL 8.0为例)  
INSTALL PLUGIN rewriter SONAME 'rewriter.so';  

-- 创建规则表  
CREATE TABLE query_rewrite.rewrite_rules (  
    pattern VARCHAR(2000) NOT NULL,  
    replacement VARCHAR(2000) NOT NULL,  
    enabled ENUM('YES','NO') DEFAULT 'YES'  
);  

-- 示例:自动为全表扫描查询添加警告  
INSERT INTO rewrite_rules (pattern, replacement)  
VALUES (  
    'SELECT * FROM orders WHERE status = ?',  
    'SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM orders WHERE status = ?'  
);  

-- 刷新规则  
CALL query_rewrite.flush_rewrite_rules();  

说明:通过MAX_EXECUTION_TIME提示强制限制执行时间,避免长查询拖垮系统。


二、五个实战场景

2.1 场景一:隐式类型转换导致索引失效

问题SQL

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM user WHERE user_id = 123; -- user_id为varchar类型  

传统优化:需人工修改为user_id='123'

Rewrite自动方案

代码语言:javascript
代码运行次数:0
运行
复制
INSERT INTO rewrite_rules (pattern, replacement)  
VALUES (  
    'SELECT * FROM user WHERE user_id = ?',  
    'SELECT * FROM user WHERE user_id = CAST(? AS CHAR)'  
);  

原理:强制将参数转换为字符串类型,确保索引生效。

2.2 场景二:深分页引发的性能灾难

问题SQL

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM logs ORDER BY create_time DESC LIMIT 100000, 10;  

传统优化:改用WHERE id > 100000 LIMIT 10或延迟关联

Rewrite自动方案

代码语言:javascript
代码运行次数:0
运行
复制
-- 规则:将深分页转换为基于主键的延迟关联  
INSERT INTO rewrite_rules (pattern, replacement)  
VALUES (  
    'SELECT * FROM logs ORDER BY create_time DESC LIMIT ?, ?',  
    'SELECT l.* FROM logs l  
     JOIN (SELECT id FROM logs ORDER BY create_time DESC LIMIT ?, ?) AS tmp  
     ON l.id = tmp.id'  
);  

效果:减少回表数据量,执行时间从5秒降至0.1秒。

2.3 场景三:IN子查询引发的临时表膨胀

问题SQL

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM products WHERE id IN (SELECT product_id FROM orders WHERE status=1);  

传统优化:改写为JOIN或分批查询

Rewrite自动方案

代码语言:javascript
代码运行次数:0
运行
复制
INSERT INTO rewrite_rules (pattern, replacement)  
VALUES (  
    'SELECT * FROM products WHERE id IN (SELECT product_id FROM orders WHERE status=?)',  
    'SELECT p.* FROM products p  
     JOIN orders o ON p.id = o.product_id AND o.status=?'  
);  

原理:避免子查询生成临时表,利用索引加速关联。

2.4 场景四:SELECT * 导致不必要的I/O消耗

问题SQL

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM employees WHERE dept_id = 5;  

传统优化:手动指定所需字段

Rewrite自动方案

代码语言:javascript
代码运行次数:0
运行
复制
INSERT INTO rewrite_rules (pattern, replacement)  
VALUES (  
    'SELECT * FROM employees WHERE dept_id = ?',  
    'SELECT id, name, position FROM employees WHERE dept_id = ?'  
);  

效果:减少数据传输量,尤其对宽表性能提升显著。

2.5 场景五:ORDER BY文件排序拖慢查询

问题SQL

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM sales WHERE region='Asia' ORDER BY amount DESC;  

传统优化:为(region, amount)添加联合索引

Rewrite自动方案

代码语言:javascript
代码运行次数:0
运行
复制
INSERT INTO rewrite_rules (pattern, replacement)  
VALUES (  
    'SELECT * FROM sales WHERE region=? ORDER BY amount DESC',  
    'SELECT /*+ INDEX(sales idx_region_amount) */ *  
     FROM sales WHERE region=? ORDER BY amount DESC'  
);  

原理:强制使用索引避免文件排序,尤其适合无法立即修改索引的场景。

三、总结

通过Rewrite插件,我们可以通过sql重写的方式,不必调整业务代码来规范mysql数据库的查询语句。这样可以解决业务实际运行过程中的许多性能问题。对于从事后端或者数据库开发的朋友来说非常有必要了解掌握一下这个技术。大家如果实际使用过程中遇到问题的话欢迎评论区沟通交流!

互动思考

在你的业务中,是否遇到过因SQL难以修改而导致的性能问题? 如果尝试使用Rewrite插件,你认为最大的挑战会是什么?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 当SQL成为性能瓶颈时,如何解决?
  • 一、Rewrite插件核心原理与配置
    • 1.1 插件工作原理
    • 1.2 安装与基础配置示例
  • 二、五个实战场景
    • 2.1 场景一:隐式类型转换导致索引失效
    • 2.2 场景二:深分页引发的性能灾难
    • 2.3 场景三:IN子查询引发的临时表膨胀
    • 2.4 场景四:SELECT * 导致不必要的I/O消耗
    • 2.5 场景五:ORDER BY文件排序拖慢查询
  • 三、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档