Hash Join是社区版MySQL 8.0版本中引入的新Join方式,可以大幅提升分析型查询的执行性能。PolarDB MySQL引擎8.0版本提供了对Hash Join的并行执行支持,并不断丰富其并行执行策略。本文介绍如何在PolarDB的并行查询中使用Hash Join功能。

简单并行Hash Join

前提条件

集群版本需为PolarDB MySQL引擎8.0集群版,且Revision version为8.0.2.1.0或以上,您可以参见查询版本号确认集群版本。

并行策略并行策略

上图中是并行度为4的并行查询计划(即PolarDB会启用4个Worker来执行查询)。其中t1表会执行Parallel Scan,即由4个Worker分别扫描这个表。每个Worker使用t1的一部分数据建立各自的Hash表,再和整个t2表执行JOIN操作,最后收集(Gather)在Leader中,得到整个查询的结果。

使用方法

  • 语法:

    目前在PolarDB中Hash Join只能通过EXPLAIN FORMAT=TREE语句来显示。

  • 示例:

    如下示例中创建了2个表,且在表里插入了一些数据:

    CREATE TABLE t1 (c1 INT, c2 INT);
    CREATE TABLE t2 (c1 INT, c2 INT);
    INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(5,5);
    INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(5,5);

    如下是上述2个表的JOIN查询计划:

    EXPLAIN FORMAT=TREE
     EXPLAIN
      -> Gather (slice: 1; workers: 4)  (cost=10.82 rows=4)
        -> Parallel inner hash join (t2.c2 = t1.c1)  (cost=0.57 rows=1)
            -> Parallel table scan on t2, with parallel partitions: 1  (cost=0.03 rows=1)
            -> Parallel hash
                -> Parallel table scan on t1, with parallel partitions: 1  (cost=0.16 rows=1)

    上述是并行度为4的并行查询计划(即PolarDB会启用4个Worker来执行查询)。其中t1表会执行Parallel Scan,即由4个Worker分扫这个表,每个Worker使用t1的一部分数据建立各自的Hash表,再和整个t2表执行JOIN操作,最后收集(Gather)在Leader,得到整个查询的结果。

并行Hash Join

前提条件

集群版本需为PolarDB MySQL引擎8.0集群版,且Revision version为8.0.2.2.0或以上,您可以参见查询版本号确认集群版本。

并行策略并行策略

上图中是并行度为4的并行查询计划(即PolarDB会启用4个Worker来执行查询)。其中t1表会执行Parallel Scan,即由4个Worker分别扫描这个表。每个Worker使用t1的一部分数据,但将构建的结果写入同一张无锁的共享hash table中。完成构建后,同一组Worker会开始对t2表执行Parallel Scan,分别扫t2。在Worker线程内完成部分数据的probe操作,最后收集(Gather)在Leader中,得到整个查询的结果。

使用方法

  • 语法:

    目前在PolarDB中Hash Join只能通过EXPLAIN FORMAT=TREE语句来显示。

  • 示例:

    如下示例中创建了2个表,且在表里插入了一些数据:

    CREATE TABLE t1 (c1 INT, c2 INT);
    CREATE TABLE t2 (c1 INT, c2 INT);
    INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(5,5);
    INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(5,5);

    如下是上述2个表的JOIN查询计划:

    EXPLAIN FORMAT=TREE
    
    EXPLAIN
    | -> Gather (slice: 1; workers: 1)  (cost=12.46 rows=4)
        -> Parallel inner hash join (t2.c1 = t1.c1)  (cost=2.06 rows=4)
            -> Parallel table scan on t2, with parallel partitions: 1  (cost=0.09 rows=4)
            -> Parallel hash
                -> Parallel table scan on t1, with parallel partitions: 1  (cost=0.65 rows=4)

Shuffle Hash Join

前提条件

集群版本需为PolarDB MySQL引擎8.0集群版,且Revision version为8.0.2.2.0或以上,您可以参见查询版本号确认集群版本。

并行策略并行策略

Parallel hash join实现了build+probe全阶段的并行执行,但如果共享的hash table较大,会导致转储到磁盘的IO操作,影响查询执行效率。因此引入了partition hash join来解决此问题。如上图所示,其中t1表会执行Parallel Scan,即由4个Worker分别扫描这个表,每个Worker使用t1的一部分数据,然后将数据按照join key做repartition的分发到下一个阶段的Worker中,在各个Worker内构建本地容量更小的hash table。完成构建后,会开始对t2表执行Parallel Scan,分别扫描这张表,同样按照join key做repartition的分发到已经完成hash table构建的Worker中。在Worker线程内完成分片数据的probe操作,最后收集(Gather)在Leader中,得到整个查询的结果。

使用方法

  • 语法:

    目前在PolarDB中Hash Join只能通过EXPLAIN FORMAT=TREE语句来显示。

  • 示例:

    如下示例中创建了2个表,且在表里插入了一些数据:

    CREATE TABLE t1 (c1 INT, c2 INT);
    CREATE TABLE t2 (c1 INT, c2 INT);
    INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(5,5);
    INSERT INTO t2 VALUES (1,1),(2,2),(3,3),(5,5);

    如下是上述2个表的JOIN查询计划:

    EXPLAIN FORMAT=TREE
    
    EXPLAIN
    | -> Gather (slice: 1; workers: 2)  (cost=33.38 rows=4)
        -> Inner hash join (t2.c1 = t1.c1)  (cost=23.08 rows=2)
            -> Repartition (hash keys: t2.c1; slice: 2; workers: 1)  (cost=11.35 rows=2)
                -> Parallel table scan on t2, with parallel partitions: 1  (cost=0.65 rows=4)
            -> Hash
                -> Repartition (hash keys: t1.c1; slice: 3; workers: 1)  (cost=11.35 rows=2)
                    -> Parallel table scan on t1, with parallel partitions: 1  (cost=0.65 rows=4)

相关视频