本文介绍了PolarDB MySQL版通过ePQ(弹性并行查询)技术来实现冷数据并行查询的方法,并提供了详细的使用说明。
背景信息
随着OSS表的使用日益普及以及存储数据量的持续增长,OSS表的查询效率问题越发凸显,严重影响使用体验。一种有效的改善策略是采用ePQ(弹性并行查询)。通过增加线程数量来显著加快查询速度,以此优化查询体验,提高数据检索效率,确保更快地获取信息。
功能说明
冷数据并行查询功能目前仅支持CSV格式的数据。通过将不同的任务分配给独立的workers来并行扫描OSS上的CSV数据,从而显著提高查询速度。其原理图如下:
版本要求
以下是对数据库引擎版本和内核小版本的具体要求:
单机并行:
数据库引擎版本为MySQL 8.0.1,内核小版本需为8.0.1.1.34及以上。
产品版本:企业版/。
单机并行:
数据库引擎版本为MySQL 8.0.2,内核小版本需为8.0.2.2.24及以上。
产品版本:企业版。
多机并行:
数据库引擎版本为MySQL 8.0.2,内核小版本需为8.0.2.2.24及以上。
产品版本:企业版。
前提条件
loose_csv_max_oss_threads表示当前节点可以并行的最大OSS线程总数。loose_csv_max_oss_threads取值范围1~100,默认值为1,如未修改将无法进行冷数据并行查询。单个OSS线程默认消耗128 MB内存,请根据实例剩余内存量适当加大loose_csv_max_oss_threads参数。
使用说明
本文的示例基于TPC-H基准运行测试,并不能与已发布的TPC-H基准测试结果进行比较,本文中的示例并不完全符合TPC-H基准测试的所有要求。查看更多详情请参见TPC-H测试集。
在开启并行查询的场景下,调大参数loose_csv_max_oss_threads即可实现冷数据的并行查询。
示例:首先归档一张OSS冷存储表,这里以lineitem
为例:
mysql> show create table lineitem;
*************************** 1. row ***************************
Table: lineitem
Create Table: CREATE TABLE `lineitem` (
`l_orderkey` int(11) NOT NULL,
`l_partkey` int(11) NOT NULL,
`l_suppkey` int(11) NOT NULL,
`l_linenumber` int(11) NOT NULL,
`l_quantity` decimal(10,2) NOT NULL,
`l_extendedprice` decimal(10,2) NOT NULL,
`l_discount` decimal(10,2) NOT NULL,
`l_tax` decimal(10,2) NOT NULL,
`l_returnflag` char(1) NOT NULL,
`l_linestatus` char(1) NOT NULL,
`l_shipDATE` date NOT NULL,
`l_commitDATE` date NOT NULL,
`l_receiptDATE` date NOT NULL,
`l_shipinstruct` char(25) NOT NULL,
`l_shipmode` char(10) NOT NULL,
`l_comment` varchar(44) NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 /*!99990 800020204 NULL_MARKER='NULL' */ CONNECTION='default_oss_server'
1 row in set (0.00 sec)
开启并行查询的方法有很多,以hint
为例,可以通过在查询中添加hint
来开启并行查询。通过查询计划可以看到,如果Extra
列中含有Parallel scan
(并行扫描)策略,则开启了并行查询,而workers数量则代表了并行度。
串行查询
通过使用EXPLAIN查询语句,可以查看Extra
列是否含有Parallel scan
标记的执行情况,从而可以判断当前线程是否处于正常的查询计划,当前并未开启并行查询。
mysql> explain SELECT
-> sum(l_extendedprice * l_discount) AS revenue
-> FROM
-> lineitem
-> WHERE
-> l_shipdate >= date '1994-01-01'
-> AND l_shipdate < date '1994-01-01' + interval '1' year
-> AND l_discount between 0.05 - 0.01 AND 0.05 + 0.01
-> AND l_quantity < 24;
+----+-------------+----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| 1 | SIMPLE | lineitem | NULL | ALL | NULL | NULL | NULL | NULL | 61560489 | 0.41 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+----------+----------+-------------+
1 row in set, 1 warning (1.23 sec)
可以观察到,在正常的查询计划中,表的聚集计算和扫描是在一个线程中串行完成。
并行查询
启用了并行查询hint
(/*+ PARALLEL(4) */)之后,执行计划显示lineitem
表正在使用并行查询来提升速度。从执行计划中的Extra
列所显示的Parallel scan
(4 workers)信息可知,本次查询正通过4个工作线程并发执行。
mysql> explain SELECT /*+ PARALLEL(4) */
-> sum(l_extendedprice * l_discount) AS revenue
-> FROM
-> lineitem
-> WHERE
-> l_shipdate >= date '1994-01-01'
-> AND l_shipdate < date '1994-01-01' + interval '1' year
-> AND l_discount between 0.05 - 0.01 AND 0.05 + 0.01
-> AND l_quantity < 24;
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+----------------------------------------+
| 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 | 4 | 100.00 | NULL |
| 1 | SIMPLE | lineitem | NULL | ALL | NULL | NULL | NULL | NULL | 15390122 | 0.41 | Parallel scan (4 workers); Using where |
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+----------------------------------------+
2 rows in set, 1 warning (2.17 sec)
可以观察到当前节点已经启用了四个workers,这意味着已经实现了并行查询,整体查询速度相当于单线程查询的四倍。
多节点并行查询
从执行计划可以看到,lineitem
表使用了Parallel scan
,每个节点计划使用4个workers来并行执行,总共有2个节点,8个workers来执行。Extra
显示了具体的workers数量和节点数量。
mysql> explain SELECT /*+ PARALLEL(4) */
-> sum(l_extendedprice * l_discount) AS revenue
-> FROM
-> lineitem
-> WHERE
-> l_shipdate >= date '1994-01-01'
-> AND l_shipdate < date '1994-01-01' + interval '1' year
-> AND l_discount between 0.05 - 0.01 AND 0.05 + 0.01
-> AND l_quantity < 24;
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+-------------------------------------------------------+
| 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 | 1 | 100.00 | NULL |
| 1 | SIMPLE | lineitem | NULL | ALL | NULL | NULL | NULL | NULL | 59986051 | 0.41 | Parallel scan (8 workers); MPP (2 nodes); Using where |
+----+-------------+-------------+------------+------+---------------+------+---------+------+----------+----------+-------------------------------------------------------+
2 rows in set, 1 warning (0.00 sec)
可以观察到,当前已经开启了2个节点执行,总线程并行度为8个线程。这意味着已经开启多节点并行查询,整体查询速度相当于单线程的查询8倍。