• 沒有找到結果。

19.1 并行查询(PQ)

19.1.1 特性使用介绍

19.1.1.1 特性使用约束

目前,并行执行在使用过程中存在一些限制,后续会逐步进行解决。

不适用并行执行的情况

下列的查询语句不支持并行执行:

● 非查询语句

● 窗口函数

● 触发器Trigger

● 空间索引Spatial index

● 查询表为系统表/临时表/非Innodb表

● 使用全文索引

● 存储过程Procedures

● 不能转换成semijoin的子查询

● Materialization simi-join

● 包含特殊字段,或者函数结果转换成特殊字段 (BLOB, JSON和GEOMETRY)

● With语句

● 使用索引归并Index merge

● 串行化隔离级别事务内的查询语句

● 带有distinct关键字的查询语句

● Require locking, such as serializable isolation level, for updata/share lock

● Attachable transaction

● 并行内存超过parallel_memory_limit限制

● 并行线程超过parallel_max_threads限制

● 执行代价未超过parallel_cost_threshold

● 递归查询

● With rollup

● 存在HIGH_PRIORITY关键字

● 执行结果返回0行数据(执行计划显示:Zero limit、Impossible WHERE、

Impossible HAVIN、No matching min/max row、No matching min/max row、Select tables optimized away、Impossible HAVING noticed after reading const tables、no matching row in const table等)

● TP高吞吐短查询模型

● group by/order by中的列是查询表达式中重命名的列

● group by中扫描代价超过非并行的语句

● 查询中包含zerofill的列,并且这些列能被优化为常量 说明

与之前的版本相比,MySQL 8.0.22版本支持了部分特性,具体如下所示:

● UNION/UNON ALL语句。

● Duplicateweedout类型的semijoin。

● Group by优化成索引扫描,并且select中包含函数表达式。

● Having中包含聚合函数

● select表达式中包含聚合函数计算,例如SUM(a)/AVG(b)。

● JOIN查询, 拆分表为内表,并且该表上是ref查询。

与串行执行结果可能不兼容

并行执行的执行结果可能存在与串行执行不兼容的情况,主要表现在:

● 错误或者告警提示次数可能会增多

对于在串行执行中出现错误/告警提示的查询,在并行执行情况下,每个工作线程 可能都会提示错误/告警,导致总体错误/告警提示数会增多。

● 精度问题

并行执行的执行过程中,当select的内容是函数类型时,会比非并行执行多出中间 结果的存储过程,可能会导致浮点部分精度差别,导致最终结果有细微的差别。

● 截断问题

并行执行的执行过程中,当select的内容是函数类型时,会比非并行执行多出中间 结果的存储过程。在这个过程中,需要缓存函数的计算结果,可能出现截断(一般 是类型转换导致的,例如浮点数类型转为字符串等), 导致最终结果与串行结果有 差别。

● 结果集顺序差别

因为是多个工作线程执行查询,返回的结果集可能与非并行执行顺序不一致。在 具有LIMIT查询的情况下,更容易出现与串行结果顺序不同的现象。对于不可见字 符,当MySQL判断多个不可见字符相等时,可能会出现结果集顺序不同,或者 group by字段不同的现象。

19.1.1.2 支持的函数、参数和变量 支持的函数

并行查询语句主要支持以下函数:

● GROUP BY

● ORDER BY

● AGGREGATION (SUM/AVG/COUNT)

● LIMIT

● WHERE/HAVING

● LIKE

● INTERVAL

● CASE WHEN

● JOIN

支持的系统参数和状态变量

19-1 系统参数

参数名 级别 描述

force_parallel_exe

cute Global, Session 强制进入并行执行,尽可能地使用并行执 行。

· 取值范围:ON, OFF

· 默认值OFF parallel_max_thre

ads Global 并行执行的最大活跃线程个数。当并行执行 的活跃线程超过该值时,新的查询将不允许 启用并行执行。

· 取值范围:0-4294967295

· 默认值:64 parallel_default_d

op Global, Session 并行执行的默认并行度。当查询语句没有指 定并行度时,使用该值。

· 取值范围:0-1024

· 默认值:4 parallel_cost_thre

shold Global, Session 启用并行执行的代价阈值。只有当查询的估 计代价超过该阈值时才有可能进行并行执 行。

· 取值范围:0-4294967295

· 默认值:1000 parallel_queue_ti

meout Global, Session 请求并行执行的SQL的等待时间。如果超过 该值后,并行执行的线程数仍然大于 parallel_max_threads,则不再等待而进入 单线程执行。

· 取值范围:0-4294967295

· 默认值:0

参数名 级别 描述 parallel_memory_

limit Global 并行执行可用的内存上限。当并行执行使用 的内存量超过该值时,新的SQL查询将不会 进行并行执行。

· 取值范围:0-4294967295

· 默认值:104857600

19-2 状态变量

变量名 级别 描述

PQ_threads_runnin

g Global 当前正在运行的并行执行的总线程数。

PQ_memory_used Global 当前并行执行使用的总内存量。

PQ_threads_refuse

d Global 由于总线程数限制,导致未能执行并行执行

的查询总数。

PQ_memory_refus

ed Global 由于总内存限制,导致未能执行并行执行的 查询总数。

19.1.1.3 开启/关闭并行查询

通过设置系统参数和使用hint语法两种方式,开启/关闭并行查询。

方法一:通过设置系统参数开启/关闭并行查询

在管理控制台的参数修改页面,通过设置系统参数开启和关闭并行查询,并设置并行 度。

通过全局参数force_parallel_execute来控制是否强制启用并行执行;

使用全局参数parallel_default_dop来控制使用多少线程并行执行;

使用全局参数parallel_cost_threshold来控制当数据规模为多大时开启并行执行。

上述参数在使用过程中,随时可以修改,无需重启数据库。

例如,想要强制开启并行执行,并且并发度为4:

SET force_parallel_execute=1;

SET parallel_default_dop=4;

SET parallel_cost_threshold=0;

方法二:使用 hint 开闭/关闭并行查询

使用hint语法可以控制单个语句是否进行并行执行。在系统默认关闭并行执行的情况 下, 可以使用hint对特定的SQL进行加速。反之,也可以限制某类SQL进入并行执行。

开启并行执行:采用下面的hint语法可以开启并行执行。

采用默认的拆分表和并发度(默认值取parallel_cost_threshold):SELECT /*+ PQ()

*/ … FROM …

采用默认的拆分表,但是指定并发度为8:SELECT /*+ PQ(8) */ … FROM … 采用默认的并发度,但是指定拆分表为t1:SELECT /*+ PQ(t1) */ … FROM … 指定拆分表为t1,并发度为8:SELECT /*+ PQ(t1 8) */ … FROM …

说明

PQ hint紧跟着SELECT关键字才能生效。PQ hint的并发度参数dop应满足:dop>0,否则此hint 不生效,如PQ(0)不生效;当dop>1024时,dop取最大并发度1024。当使用PQ hint时,支持多 表查询。

关闭并行执行:可以采用"NO_PQ"的hint语法关闭并行执行。

SELECT /*+ NO_PQ */ … FROM …

19.1.1.4 查看特性状态

状态显示

通过show status like "%PQ%",显示并行执行的当前状态,显示结果请见图1:

19-2 状态显示

并行执行计划展示

通过Explain展示查询语句的并行执行计划,显示结果请见图2:

19-3 并行执行计划结果展示

说明

与传统的执行计划,并行执行计划多了一行记录。在查询结果的第一行,展示了并发度、拆分表 等信息。对于Explain format=json和Explain format=tree格式,并行执行目前还不支持。

19.1.1.5 并行执行中多表支持介绍

并行执行新增支持多表join查询功能,并且新增hint语法控制单条语句并行执行开启或 关闭。

多表支持限制

并行执行多表join支持:

● BNL(hash join)

● BKA

● Semijoin Firstmatch, loosescan和DuplicateWeedout

● outer join(仅支持拆分外表)

并行执行多表join不支持的方式:

● Semijoin Materialization

● 不能转换成semijoin的子查询

● Join的表有相同的alias 并行执行不支持的数据类型:

● generated column

● BLOB(TINYBLOB, BLOB, MEDIUMBLOB, and LONGBLOB等)

● TEXT

● JSON

● GEOMETRY

并行执行不支持的函数:

● Spatial相关函数(如SP_WITHIN_FUNC等)

● aggregation(distinct)(如sum(distinct)、avg(distinct)、count(distinct))

● GROUP_CONCAT

● JSON_ARRAYAGG/JSON_OBJECTAGG

● 用户自定义函数

● STD/STDDEV/STDDEV_POP

● VARIANCE/VAR_POP/VAR_SAMP

● BIT_AND, BIT_OR and BIT_XOR

● set_user_var

● rand(不含参数的除外)

● json_*(如json_length,json_type等)

● st_distance

● get_lock

● is_free_lock,is_used_lock,release_lock, release_all_locks

● sleep

● xml_str

● weight_string

● ref函数(VIEW_REF, OUTER_REF, AGGREGATE_REF),

● SHA,SHA1,SHA2,MD5

拆分表选择策略

1. 优先选择hint指定的表,并坚持是否能作为拆分表。

2. 若未使用PQ HINT指定拆分表,或者hint指定的表不能作为拆分表,则选择行记 录最多的表(根据统计信息中row_fetched)。

3. 若行记录最多的表不能作为拆分表,则选择行记录次数多的。

4. 直到选择一个能拆分的表,则选择此表作为拆分表,进行并行执行。或者全部表 都不支持拆分,不走并行执行。

拆分表选择限制

不支持作为拆分表的表类型:

● 非table/index/range scan

● outer join的内表

● const/system不支持拆分

● 可为空(nullable)的表不支持拆分

● skip scan

可能出现的性能退化

● 表数据量过小

在小表上启用并行查询,此场景下有性能退化。

● 拆分表选择不合适

由于拆分表选择上有限制,有些场景下只能选择最外层的表作为拆分表,但是此 表可能只存在几行数据,不能充分利用所有worker线程,并行性能退化。

20 使用规范建议

相關文件