前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PolarDB 并行黑科技--从百套MySQL撤下说起

PolarDB 并行黑科技--从百套MySQL撤下说起

作者头像
AustinDatabases
发布于 2024-11-25 03:01:17
发布于 2024-11-25 03:01:17
21300
代码可运行
举报
文章被收录于专栏:AustinDatabasesAustinDatabases
运行总次数:0
代码可运行

使用PolarDB-M(PolarDB for MySQL)已经有3年的时间了,作为PolarDB 非官方专业的技术传播渠道也有一段时间。替换MySQL到PolarDB-M,从当初的架构师,开发对这个云原生数据库的质疑,到现在一百多套的MySQL都消失了,拔地而起的一百多套的PolarDB-M,过程重要,结果也重要,其实都重要,如果没有结果,那么过程的目的又是什么。

今天我们就来说说深度使用PolarDB-M的用户,对于PolarDB-M拿手的技能,“并行”的一些使用经验和问题。(这也仅仅是第一期)

一、为什么要并行这个问题与两个事情有关

1 硬件的发展与数据库处理query之间的矛盾:硬件在发展的过程中,CPU的处理能力与CPU的核心数成关联性,数据库在处理数据查询的过程中,无法利用更先进的硬件。导致再多的CPU给付了数据库系统,也无法再一个SQL中发挥作用,单个SQL的处理速度并未因为CPU更多,而有更快的速度。

2 OLAP数据在传统数据库的处理 传统数据库在数据处理中,逐渐呈现多元化的发展道路,在数据处理中OLAP在线分析的工作在传统数据库中进行了延伸。更多的数据需要更多的CPU处理的需求逐渐被放大。

所以后续的数据库产生了并行处理SQL语句的功能,但并行查询并非是一个万全其美的好事,而是有利有弊的事情。

二、并行处理到底哪里并行

这个问题还的从一个SQL处理中哪个部分慢来说明,基于硬件的限制,每次IO的耗时是处理SQL中的一个难点,虽然后续有了SSD等磁盘系统,但如果有更多的线程来处理一个SQL中的数据,将是解决当前单个SQL数据处理中的一个解决方案,这也就是我们经常提起的并行读取。

三、如何并行

在进行并行处理的过程中,需要考虑的问题有很多

1 一个SQL我到底要不要进行并行

2 一个SQL我到底要怎么拆分

3 我怎么分配我的CPU资源去处理这些拆分的数据

4 我在处理了这些数据后,我们怎么合并这些数据,组成一个最终的结果

在这些问题提出后,我们必须去解决这些问题,其中解决这些问题的关键,cost 代价,代价是评价一个SQL到底值不值得进行拆分的关键,同时随着语句的复杂,多个表进行JOIN的情况下,则并行处理SQL将变得更加的复杂,Join中的每个表都有自己的进行数据处理的方式,如ref索引扫描,全表扫描,range索引扫描等等,这些都会影响到最终的并行扫描的代价。

关于并行的理论的部分很复杂,我们暂时先放到一边,我们先从实际的情况来,来对PolarDB的并行的部分进行一个感性的认知。

四、PolarDB的并行参数

PolarDB-M

max_parallel_degree : 参数主要是负责单个查询的最大并行度,范围0-1024,PolarDB优化器可能会对主查询和子查询分别并行执行,如果同时并行执行,它们的最大Worker数不能超过max_parallel_degree的值。

parallel_degree_policy: 云原生数据库查询并行度的策略,这里有三个策略 1 Typical:直接进行并行,对于系统的负载不考虑 2 Auto: 根据数据库的负载进行是否进行并行的选择,主从库均会进行查询的并行负载执行 3 Replica_AUTO:这是默认的选项,仅仅读库进行查询的并行开启,且要考虑具体的CPU负载情况

parallel_workers_policy: 1 local: 强制本机进行并行 2 AUTO:开启弹性并行,在本地资源不足的情况下,去使用其他节点的资源来进行SQL的计算,比如你有两个只读的节点,A节点资源不足,A节点进行并行的时候,直接找B节点CPU进行SQL的计算。3 Multi_nodes: 强制多机器并行进行查询的支持

records_threshold_for_parallelism:在优化器估算语句的情况下,当扫描的记录数超过阈值,优化器会考虑使用并行计划 默认值 10000

cost_threshold_for_parallelism: 在优化器进行估算查询代价时,串行超过该阈值,优化器会考虑选择并行执行计划。 默认值:50000

records_threshold_for_mpp: 在表扫描中,行数超过阈值则进行堆积并行的执行方式 默认值0

cost_threshold_for_mpp: 查询语句的串行代价超过法治后,优化器就会考虑并行的执行方式

说完这些参数后,可能有些没有学过PostgreSQL的老师,可能对这个部分比较的模糊,但学过PostgreSQL的知识和参数后,发现这和PostgreSQL可以任意调整COST引擎计算值的方案如出一辙。

这里简单的总结,PolarDB for MySQL里面对于并行的灵活调配的程度是非常高的,这里参数如果分类可以分为

1 单条语句是否要进行并行

2 JOIN 多条语句是否要并行

3 是否采用多主机的并行资源共享

4 并行的范围,读写节点,读节点,关闭

相对来说,我们也可以通过变量来进行数据库状态的分析

Parallel_worker_created 从Session启动开始,生成Parallel Worker的个数

Gather_records Gather记录总数

PQ_refused_over_total_workers 由于总Worker数限制没有启用并行的查询数

PQ_REFUSED_OVER_MAX_QUEUING_TIME

由于并行查询排队超时没有启动并行的查询数

Total_running_parallel_workers

当前正在运行的Parallel Worker的数目。

写到这里,我们要开始利用这些参数来帮助我们针对并行的问题做点什么

1 到底当前的主机的CPU够不够用,当并行开启后,一定要对主机的状态有一个判断,而不是去光分析慢查询语句,在发现慢查询语句的同时,要针对由于资源不足导致的语句没有走并行的语句进行一个统计。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MySQL []> show status like 'PQ_REFUSED_OVER_MAX_QUEUING_TIME'; 
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| PQ_refused_over_max_queuing_time | 0     |
+----------------------------------+-------+
1 row in set (0.004 sec)

MySQL []> show status like 'PQ_refused_over_total_workers';    
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| PQ_refused_over_total_workers | 0     |
+-------------------------------+-------+
1 row in set (0.004 sec)

通过这个命令来,针对查看基于总体的资源应该用并行,但没有走并行的语句,在一个时间段是否在快速增长,且持续增长。从这里就可以看出两个问题。

1 CPU资源不足

2 配置参数需要优化

3 有大量的语句需要进行优化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MySQL [dba_test]> explain SELECT 
    ->     s.student_id,
    ->     s.name,
    ->     AVG(sc.math_score) AS avg_math_score,
    ->     AVG(sc.english_score) AS avg_english_score,
    ->     AVG(sc.chinese_score) AS avg_chinese_score
    -> FROM 
    ->     students s
    -> JOIN 
    ->     scores sc ON s.student_id = sc.student_id
    -> GROUP BY 
    ->     s.student_id, s.name;
+----+-------------+-------------+------------+------+---------------+------------+---------+-----------------------+-------+----------+--------------------------------------------+
| id | select_type | table       | partitions | type | possible_keys | key        | key_len | ref                   | rows  | filtered | Extra                                      |
+----+-------------+-------------+------------+------+---------------+------------+---------+-----------------------+-------+----------+--------------------------------------------+
|  1 | SIMPLE      | <gather1.1> | NULL       | ALL  | NULL          | NULL       | NULL    | NULL                  | 91399 |   100.00 | NULL                                       |
|  1 | SIMPLE      | s           | NULL       | ALL  | PRIMARY       | NULL       | NULL    | NULL                  | 22850 |   100.00 | Parallel scan (4 workers); Using temporary |
|  1 | SIMPLE      | sc          | NULL       | ref  | student_id    | student_id | 5       | dba_test.s.student_id |     3 |   100.00 | NULL                                       |
+----+-------------+-------------+------------+------+---------------+------------+---------+-----------------------+-------+----------+--------------------------------------------+
3 rows in set, 1 warning (0.003 sec)

从上面的语句可以看到PolarDB for MySQL中启用了并行,且还是4个线程的并行。

这里修改了参数,将max_parallel_degree修改成2 ,这里需要注意如果在之前的已经连接的POLARDB-M 的线程中,这个参数还是 4 是无法改变的,参数生效只针对新的连接,这点需要注意。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MySQL [dba_test]> explain SELECT      s.student_id,     s.name,     AVG(sc.math_score) AS avg_math_score,     AVG(sc.english_score) AS avg_english_score,     AVG(sc.chinese_score) AS avg_chinese_score FROM
    ->  students s JOIN      scores sc ON s.student_id = sc.student_id GROUP BY      s.student_id, s.name;
+----+-------------+------------------+------------+------+---------------+------------+---------+-----------------------+-------+----------+---------------------------+
| id | select_type | table            | partitions | type | possible_keys | key        | key_len | ref                   | rows  | filtered | Extra                     |
+----+-------------+------------------+------------+------+---------------+------------+---------+-----------------------+-------+----------+---------------------------+
|  1 | SIMPLE      | <gather1.1>      | NULL       | ALL  | NULL          | NULL       | NULL    | NULL                  | 91399 |   100.00 | NULL                      |
|  1 | SIMPLE      | <repartition1.2> | NULL       | ALL  | NULL          | NULL       | NULL    | NULL                  | 45700 |   100.00 | Using temporary           |
|  1 | SIMPLE      | <repartition1.3> | NULL       | ALL  | NULL          | NULL       | NULL    | NULL                  | 45700 |   100.00 | Using temporary           |
|  1 | SIMPLE      | s                | NULL       | ALL  | PRIMARY       | NULL       | NULL    | NULL                  | 45700 |   100.00 | Parallel scan (2 workers) |
|  1 | SIMPLE      | sc               | NULL       | ref  | student_id    | student_id | 5       | dba_test.s.student_id |     3 |   100.00 | NULL                      |
+----+-------------+------------------+------------+------+---------------+------------+---------+-----------------------+-------+----------+---------------------------+
5 rows in set, 1 warning (0.003 sec)


前两天,梁大师SQL的一篇文章也提到了并行,并行本身只是一种技术,他可以提高你的SQL效率,也可以降低,这点我在PostgreSQL上也深有体会,开了并行比不开并行还快的真实场景。但并行本身是一种技术的进步,且并行在云原生数据库上的并行还有更深的发挥余地和比单体数据库更大的扩展空间。

写到这里,还没有写到真正的PolarDB的黑科技,跨机并行,不过一看字数2229了,那就先写到这里,后面可以继续写一些云原生数据库中更深的东西。

最后写一写最近学习数据库的感触,干数据库这个工作也20年了,经历了Sql SERVER---> MySQL--->Tidb---> MongoDB--->PostgreSQL--->Redis--->PolarDB-M --->OceanBase--->PolarDB-P。

传统数据库-->缓存数据库--->分布式存储数据库---云原生数据库--->分布式云原生数据库

这一路有些数据库的学习越来越有趣,有些库已经离我越来越远,有些数据库越来越近,不过一直在学习和往前走着,没有停下,数据库的架构一直在更新,已经和我10年前,5年前,甚至3年前的东西相比日新月异,这证明他们也在进步,那么正在读这篇文章的你呢?加油

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AustinDatabases 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档