返回顶部
首页 > 资讯 > 数据库 >ProxySQL Query Rewrite 使用示例
  • 455
分享到

ProxySQL Query Rewrite 使用示例

2024-04-02 19:04:59 455人浏览 薄情痞子
摘要

在这篇文章中,我将重新探究Proxysql中的Query Rewrite功能,因为query rewriting是创建ProxySQL的最根本初衷。 为什么我们需要重写查询? 你已经确定了一个触发性能

在这篇文章中,我将重新探究Proxysql中的Query Rewrite功能,因为query rewriting是创建ProxySQL的最根本初衷。

为什么我们需要重写查询?

  • 你已经确定了一个触发性能瓶颈或导致系统缓慢的查询
  • 你无法(快速的)修改应用代码
  • 某些特殊的操作需要“重定向查询”

这儿举例你作为DBA发现了一个“坏查询”,你确认是它导致了服务缓慢,并且可能会导致服务不可用。那这个查询必须被优化,你和开发沟通要修正这个SQL,但是开发反馈回来的信息是能改,但是由于技术的非技术的种种原因吧,没有那么快。这时你怎么办,等着?显然不能,你可以在开发完成修正之前通过ProxySQL的Query Rewrite功能重写某些查询来完成优化同时对应用保持透明。

如何重写查询?通过ProxySQL有两种方式来完成(译者注:其实应该理解为两种匹配查询的方式)。

Query rewrite其实就是通过 Mysql_query_rules 表中一个 match_pattern + replace_pattern 的过程,而match_digest (注意区分 match_pattern 和 match_digest )仅用来匹配一个查询,而非重写它。逻辑上讲,match_digestusernameschemanameproxy_addr 等字段的作用是一样的,仅用来匹配查询。

这两种不同的机制为不同的查询类型(例如DML操作,SELECT等)提供了灵活高效匹配方式。注意如果你希望重写查询,那么规则中的match_pattern必须能匹配到原始的查询。查询规则按照rule_id字段的升序顺序处理,并且只有在active字段为1的前提下才会处理。

下面是我们如何在我们的测试环境演示 match_digest

mysql> SELECT hostgroup hg, sum_time, count_star, digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC limit 10;
+----+-----------+------------+-----------------------------------+
| hg | sum_time  | count_star | digest_text                       |
+----+-----------+------------+-----------------------------------+
| 0  | 243549572 | 85710      | SELECT c FROM sbtest10 WHERE id=? |
| 0  | 146324255 | 42856      | COMMIT                            |
| 0  | 126643488 | 44310      | SELECT c FROM sbtest7 WHERE id=?  |
| 0  | 126517140 | 42927      | BEGIN                             |
| 0  | 123797307 | 43820      | SELECT c FROM sbtest1 WHERE id=?  |
| 0  | 123345775 | 43460      | SELECT c FROM sbtest6 WHERE id=?  |
| 0  | 122121030 | 43010      | SELECT c FROM sbtest9 WHERE id=?  |
| 0  | 121245265 | 42400      | SELECT c FROM sbtest8 WHERE id=?  |
| 0  | 120554811 | 42520      | SELECT c FROM sbtest3 WHERE id=?  |
| 0  | 119244143 | 42070      | SELECT c FROM sbtest5 WHERE id=?  |
+----+-----------+------------+-----------------------------------+
10 rows in set (0.00 sec)
mysql> INSERT INTO mysql_query_rules (rule_id,active,username,match_digest, match_pattern,replace_pattern,apply) VALUES (10,1,'root','SELECT.*WHERE id=?','sbtest2','sbtest10',1);
Query OK, 1 row affected (0.00 sec)
mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| 0    | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2       | sbtest10        | NULL      | 1     |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
1 row in set (0.00 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| 593  | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2       | sbtest10        | NULL      | 1     |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
1 row in set (0.00 sec)

如果想清空 query rules 的统计信息,使用下列方法

mysql> SELECT 1 FROM stats_mysql_query_digest_reset LIMIT 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.01 sec)
mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)

接下来是 match_pattern 示例:

mysql> SELECT hostgroup hg, sum_time, count_star, digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC limit 5;
+----+----------+------------+----------------------------------+
| hg | sum_time | count_star | digest_text                      |
+----+----------+------------+----------------------------------+
| 0  | 98753983 | 16292      | BEGIN                            |
| 0  | 84613532 | 16232      | COMMIT                           |
| 1  | 49327292 | 16556      | SELECT c FROM sbtest3 WHERE id=? |
| 1  | 49027118 | 16706      | SELECT c FROM sbtest2 WHERE id=? |
| 1  | 48095847 | 16396      | SELECT c FROM sbtest4 WHERE id=? |
+----+----------+------------+----------------------------------+
5 rows in set (0.01 sec)

mysql> INSERT INTO mysql_query_rules (rule_id,active,username,match_pattern,replace_pattern,apply) VALUES (20,1,'root','DISTINCT(.*)ORDER BY c','DISTINCT1',1);
Query OK, 1 row affected (0.00 sec)

mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern          | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
| 0    | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2                | sbtest10        | NULL      | 1     |
| 0    | 20      | NULL   | 1      | root     | NULL               | DISTINCT(.*)ORDER BY c | DISTINCT1      | NULL      | 1     |
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
2 rows in set (0.01 sec)

mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern          | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
| 9994 | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2                | sbtest10        | NULL      | 1     |
| 6487 | 20      | NULL   | 1      | root     | NULL               | DISTINCT(.*)ORDER BY c | DISTINCT1      | NULL      | 1     |
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
2 rows in set (0.00 sec)

mysql> SELECT 1 FROM stats_mysql_query_digest_reset LIMIT 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql>  LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)

路由规则中一个关键点是 mysql_query_rules 的 apply 字段

  • apply = 1(默认)表示查询一旦匹配到一条规则就不再匹配剩余的规则
  • apply = 0 表示继续尝试匹配后续的规则

(译者注:类似于Nginx rewrite 指令中的 break 参数)

如下面测试中所展示的,所有匹配rule_id = 10 或 rule_id = 20 的查询都准确的匹配上了。实际上,现在所有的规则在 runtime_mysql_query_rules 表中都是激活的。如果我们想禁用 mysql_query_rules 表中某条规则,设置 active = 0

mysql> update mysql_query_rules set apply = 1 where rule_id in (10);
Query OK, 1 row affected (0.00 sec)
mysql> update mysql_query_rules set apply = 0 where rule_id in (20);
Query OK, 1 row affected (0.00 sec)
mysql>  LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern          | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
| 0    | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2                | sbtest10        | NULL      | 1     |
| 0    | 20      | NULL   | 1      | root     | NULL               | DISTINCT(.*)ORDER BY c | DISTINCT1      | NULL      | 0     |
+------+---------+--------+--------+----------+--------------------+------------------------+-----------------+-----------+-------+
2 rows in set (0.00 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, flagIN, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+-------+---------+--------+--------+----------+--------------------+------------------------+-----------------+--------+-------+
| hits  | rule_id | digest | active | username | match_digest       | match_pattern          | replace_pattern | flagIN | apply |
+-------+---------+--------+--------+----------+--------------------+------------------------+-----------------+--------+-------+
| 10195 | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2                | sbtest10        | 0      | 1     |
| 6599  | 20      | NULL   | 1      | root     | NULL               | DISTINCT(.*)ORDER BY c | DISTINCT1      | 0      | 0     |
+-------+---------+--------+--------+----------+--------------------+------------------------+-----------------+--------+-------+
2 rows in set (0.00 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, flagIN, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+-------+---------+--------+--------+----------+--------------------+------------------------+-----------------+--------+-------+
| hits  | rule_id | digest | active | username | match_digest       | match_pattern          | replace_pattern | flagIN | apply |
+-------+---------+--------+--------+----------+--------------------+------------------------+-----------------+--------+-------+
| 20217 | 5       | NULL   | 1      | root     | NULL               | DISTINCT(.*)ORDER BY c | DISTINCT1      | 0      | 1     |
| 27020 | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2                | sbtest10        | 0      | 0     |
+-------+---------+--------+--------+----------+--------------------+------------------------+-----------------+--------+-------+
2 rows in set (0.00 sec)
mysql> update mysql_query_rules set active = 0 where rule_id = 5;
Query OK, 1 row affected (0.00 sec)
mysql>  LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.02 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| 0    | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2       | sbtest10        | NULL      | 0     |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
1 row in set (0.00 sec)
mysql> SELECT hits, mysql_query_rules.rule_id,digest,active,username, match_digest, match_pattern, replace_pattern, cache_ttl, apply FROM mysql_query_rules NATURAL JOIN stats.stats_mysql_query_rules ORDER BY mysql_query_rules.rule_id;
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| hits | rule_id | digest | active | username | match_digest       | match_pattern | replace_pattern | cache_ttl | apply |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
| 4224 | 10      | NULL   | 1      | root     | SELECT.*WHERE id=? | sbtest2       | sbtest10        | NULL      | 0     |
+------+---------+--------+--------+----------+--------------------+---------------+-----------------+-----------+-------+
1 row in set (0.01 sec)

另外,ProxySQL还能帮忙识别出“低效的查询”,登录管理界面按如下操作
找出总耗时最多的查询

mysql> SELECT SUM(sum_time), SUM(count_star), digest_text FROM stats_mysql_query_digest GROUP BY digest ORDER BY SUM(sum_time) DESC LIMIT 3G
*************************** 1. row ***************************
  SUM(sum_time): 95053795
SUM(count_star): 13164
    digest_text: BEGIN
*************************** 2. row ***************************
  SUM(sum_time): 85094367
SUM(count_star): 13130
    digest_text: COMMIT
*************************** 3. row ***************************
  SUM(sum_time): 52110099
SUM(count_star): 13806
    digest_text: SELECT c FROM sbtest3 WHERE id=?
3 rows in set (0.00 sec)

找出平均耗时最高的查询

mysql> SELECT SUM(sum_time), SUM(count_star), SUM(sum_time)/SUM(count_star) avg,  digest_text FROM stats_mysql_query_digest GROUP BY digest ORDER BY SUM(sum_time)/SUM(count_star) DESC limit 1;
+---------------+-----------------+--------+--------------------------------+
| SUM(sum_time) | SUM(count_star) | avg    | digest_text                    |
+---------------+-----------------+--------+--------------------------------+
| 972162        | 1               | 972162 | CREATE INDEX k_5 ON sbtest5(k) |
+---------------+-----------------+--------+--------------------------------+
1 row in set (0.00 sec)

我发现关于ProxySQL query rewrite 的“最好”的文档在IBM,这里介绍了查询重写的原理和示例,值得一读。

还有一些别的场景你可能需要重写查询,试想有一张表的自增ID列已经达到了int类型的最大值,你可以将新插入的数据重定向到另一张表同时你通过alter命令来修正原表的问题,在这期间所有的查询还将访问原表,等alter原表完成后,将新表的数据导入的原表,即可达到不停机修DDL的效果。

从MySQL 5.7.6 起,MySQL以插件形式提供了 query rewrite 功能,你可以在这里找到相关文档。MySQL内建的查询重写功能的一个最大的劣势在于重写规则仅作用于当前MySQL实例,这也是相比之下ProxySQL 的优势所在:它处在应用和数据库之间,所以它的重写规则是全局的。

原文链接

您可能感兴趣的文档:

--结束END--

本文标题: ProxySQL Query Rewrite 使用示例

本文链接: https://lsjlt.com/news/41904.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • ProxySQL Query Rewrite 使用示例
    在这篇文章中,我将重新探究ProxySQL中的Query Rewrite功能,因为query rewriting是创建ProxySQL的最根本初衷。 为什么我们需要重写查询? 你已经确定了一个触发性能...
    99+
    2024-04-02
  • 怎么使用Mysql的Query-rewrite
    本篇内容介绍了“怎么使用Mysql的Query-rewrite”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
  • Oracle如何使用物化视图查询重写query rewrite
    这篇文章主要介绍了Oracle如何使用物化视图查询重写query rewrite,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。 ...
    99+
    2024-04-02
  • MySQL中Query Cache的示例分析
    小编给大家分享一下MySQL中Query Cache的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、原理概述Query Cache就是把“查询返回的结...
    99+
    2023-06-20
  • Spring Data JPA 在 @Query 中使用投影的方法示例详解
    Spring Data JPA 在 @Query 中使用投影的方法 关于投影的基本使用可以参考这篇文章:https://www.baeldung.com/spring-data-jp...
    99+
    2024-04-02
  • mysql中slow query log的示例分析
    这篇文章将为大家详细讲解有关mysql中slow query log的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 由于最近自己管理的mysql有出现查询慢的...
    99+
    2024-04-02
  • Elasticsearch查询之Term Query示例解析
    目录Term Query基本语法Java代码写法Terms-匹配多个值基本语法Java写法Term查询可配置的其他参数总结Term Query Term Query是一种最基本的查询...
    99+
    2023-05-17
    Elasticsearch Term查询 Elasticsearch Term
  • Pandas使用query()优雅的查询实例
    目录常规用法多条件查询引用变量索引选取多索引选取特殊字符对于 Pandas 根据条件获取指定数据,相信大家都能够轻松的写出相应代码,但是如果你还没用过 query,相信你会被它的简洁...
    99+
    2024-04-02
  • ReactQuery系列React Query 实践示例详解
    目录引言客户端状态 vs 服务端状态React Query关于默认行为的解释使用React Query DevTools把query key理解成一个依赖列表一个新的缓存入口把服务端...
    99+
    2022-11-13
    React Query 实践 ReactQuery 系列
  • nginx rewrite功能如何使用
    今天小编给大家分享一下nginx rewrite功能如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前言大家...
    99+
    2023-06-30
  • MySQL使用ProxySQL实现读写分离
    1 ProxySQL简介: ProxySQL是一个高性能的MySQL中间件,拥有强大的规则引擎。官方文档:https://github.com/sysown/proxysql/wiki/下载地址:https...
    99+
    2024-04-02
  • 怎么使用mysqlbinlog rewrite-db选项
    本篇内容介绍了“怎么使用mysqlbinlog rewrite-db选项”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能...
    99+
    2024-04-02
  • nginx使用rewrite报错的解决
    目录项目场景:问题描述原因分析:解决方案:项目场景: 今天编译安装nginx的时候想着要做rewrite功能,匆忙瞟了一眼编译文档就直接make&&make inst...
    99+
    2023-03-08
    nginx rewrite报错 nginx rewrite
  • 详解Spring Data JPA使用@Query注解(Using @Query)
    经过几天的折腾,终于到了学习一个重量级的查询方式上,使用@Query注解,使用注解有两种方式,一种是JPQL的SQL语言方式,一种是原生SQL的语言,略有区别,后者我们更熟悉一些。话不多说,看代码。1、在CustomerRepository...
    99+
    2023-05-31
    spring data jpa
  • Excel 曝Power Query安全漏洞的示例分析
    Excel 曝Power Query安全漏洞的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。近日,Mimecast 威胁中心的安全研究人员,发现了微软 Excel ...
    99+
    2023-06-05
  • rewrite模块怎么在Nginx中使用
    rewrite模块怎么在Nginx中使用?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。rewrite模块即ngx_http_rewrite_module模块,主要功能是改写...
    99+
    2023-06-06
  • nginx使用rewrite报错如何解决
    今天小编给大家分享一下nginx使用rewrite报错如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。问题描述由于本人...
    99+
    2023-07-05
  • 怎样使用pt-query-digest
    这期内容当中小编将会给大家带来有关怎样使用pt-query-digest,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.语法及重要选项pt-query-digest [...
    99+
    2024-04-02
  • @Query注解如何使用
    这篇文章主要讲解了“@Query注解如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“@Query注解如何使用”吧!@Query注解的用法1.一个使用@Query注解的简单例子@Quer...
    99+
    2023-06-29
  • python pandas query的使用方法
    前言: Pandas 中应用 query 函数来进行数据筛选。 query 函数的一般用法如下: df.query('expression') 常用方法: #!/usr/bin/py...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作