冷数据并行查询

本文介绍了PolarDB MySQL版通过ePQ(弹性并行查询)技术来实现冷数据并行查询的方法,并提供了详细的使用说明。

背景信息

随着OSS表的使用日益普及以及存储数据量的持续增长,OSS表的查询效率问题越发凸显,严重影响使用体验。一种有效的改善策略是采用ePQ(弹性并行查询)。通过增加线程数量来显著加快查询速度,以此优化查询体验,提高数据检索效率,确保更快地获取信息。

功能说明

冷数据并行查询功能目前仅支持CSV格式的数据。通过将不同的任务分配给独立的workers来并行扫描OSS上的CSV数据,从而显著提高查询速度。其原理图如下:

image

版本要求

以下是对数据库引擎版本和内核小版本的具体要求:

  • 单机并行:

    • 数据库引擎版本为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倍。