14.9.5 查询路由与规则性能优化

在ProxySQL中,查询路由与规则性能优化的核心目标是降低解析与匹配开销、缩短路由判定路径、提升热点请求吞吐,并确保规则可维护与可观测。

原理草图:查询路由与规则匹配链路#

文章图片

路由规则设计原则#

  • 最少规则原则:以业务维度合并规则,避免重复与冗余的正则匹配。
  • 先易后难:将低成本匹配(digest/模式前缀)放在高优先级,复杂正则置于后位。
  • 稳定优先:优先使用digestschemanameusername等稳定字段,减少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_digestmatch_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) 导出当前规则并进行一次回滚演练,确认规则恢复有效。