14.9.5 查询路由与规则性能优化
在ProxySQL中,查询路由与规则性能优化的核心目标是降低解析与匹配开销、缩短路由判定路径、提升热点请求吞吐,并确保规则可维护与可观测。
原理草图:查询路由与规则匹配链路#
路由规则设计原则#
- 最少规则原则:以业务维度合并规则,避免重复与冗余的正则匹配。
- 先易后难:将低成本匹配(digest/模式前缀)放在高优先级,复杂正则置于后位。
- 稳定优先:优先使用
digest、schemaname、username等稳定字段,减少match_pattern复杂正则依赖。 - 职责单一:规则负责路由或重写,不混杂多种逻辑,便于审计与回滚。
规则匹配性能优化(含命令)#
1)查看现有规则与命中率#
-- 连接ProxySQL管理端
mysql -u admin -padmin -h 127.0.0.1 -P6032
-- 查看规则与优先级
SELECT rule_id, active, apply, match_digest, match_pattern, destination_hostgroup, weight, comment
FROM mysql_query_rules
ORDER BY rule_id;
-- 查看规则命中统计
SELECT rule_id, hits, sum_time, digest
FROM stats_mysql_query_rules
ORDER BY hits DESC
LIMIT 10;
预期效果:识别高命中/低命中规则,作为优化优先级依据。
2)用digest替代复杂正则#
-- 将高频SQL用match_digest替代正则
INSERT INTO mysql_query_rules
(rule_id, active, apply, match_digest, destination_hostgroup, comment)
VALUES
(1001, 1, 1, '^SELECT .* FROM orders WHERE user_id = \\?$', 20, 'orders读路由');
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
解释:match_digest比match_pattern正则开销更低,优先使用。
3)禁用无效规则降低匹配链路#
UPDATE mysql_query_rules
SET active=0, apply=0, comment='历史规则禁用'
WHERE rule_id=2009;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
预期效果:减少规则链路长度,降低CPU消耗。
读写分离与路由分组优化(含示例)#
-- 后端分组:10为写,20为读
INSERT INTO mysql_servers
(hostgroup_id, hostname, port, weight, max_connections)
VALUES
(10, '10.0.0.10', 3306, 1, 200),
(20, '10.0.0.11', 3306, 1, 200),
(20, '10.0.0.12', 3306, 1, 200);
-- 读路由
INSERT INTO mysql_query_rules
(rule_id, active, apply, match_digest, destination_hostgroup, comment)
VALUES
(1101, 1, 1, '^SELECT .* FROM orders', 20, 'orders读');
-- 写路由
INSERT INTO mysql_query_rules
(rule_id, active, apply, match_digest, destination_hostgroup, comment)
VALUES
(1102, 1, 1, '^INSERT .* INTO orders', 10, 'orders写');
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
命令解释:destination_hostgroup决定SQL路由到哪个组,写优先走主库组。
规则命中与可观测性(含排错)#
-- 识别高耗时规则
SELECT rule_id, hits, sum_time, (sum_time/hits) avg_time_us
FROM stats_mysql_query_rules
WHERE hits > 0
ORDER BY avg_time_us DESC
LIMIT 10;
-- 识别高频SQL摘要
SELECT digest, count_star, sum_time, hostgroup
FROM stats_mysql_query_digest
ORDER BY count_star DESC
LIMIT 10;
排错提示:
- 若avg_time_us高:优先检查match_pattern是否复杂。
- 若某规则hits=0:可能被更高优先级规则覆盖,需检查rule_id排序。
SQL改写与分流优化(含示例)#
-- 仅对指定业务进行改写,避免全局CPU消耗
INSERT INTO mysql_query_rules
(rule_id, active, apply, match_pattern, replace_pattern, destination_hostgroup, comment)
VALUES
(1201, 1, 1, '^SELECT \\* FROM t_user', 'SELECT id,name FROM t_user', 20, '只改写核心字段');
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
解释:replace_pattern仅对高收益SQL启用,避免无必要改写。
变更与回滚策略(含命令)#
-- 规则快照(导出)
SELECT * FROM mysql_query_rules
INTO OUTFILE '/tmp/proxysql_rules_backup.sql';
-- 回滚(导入)
SOURCE /tmp/proxysql_rules_backup.sql;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
注意:若权限不足,需调整secure_file_priv或通过管理端导出。
常见问题与排错步骤#
1) 高CPU
- 排查:
sql
SELECT rule_id, hits, sum_time FROM stats_mysql_query_rules ORDER BY sum_time DESC LIMIT 5;
- 处理:将高耗时正则替换为match_digest,并降低规则数量。
2) 路由不稳定
- 排查:
sql
SELECT rule_id, match_pattern, destination_hostgroup FROM mysql_query_rules ORDER BY rule_id;
- 处理:检查是否多条规则命中同一SQL,调整优先级或增加约束字段。
3) 误分流
- 排查:
sql
SELECT rule_id, username, schemaname, match_pattern FROM mysql_query_rules;
- 处理:补充username/schemaname限定,提高精确度。
练习#
1) 创建两条规则:一条用match_pattern,一条用match_digest,比较命中耗时。
2) 将一个高频正则规则替换为match_digest并验证CPU变化。
3) 导出当前规则并进行一次回滚演练,确认规则恢复有效。