前言

本特性自MogDB 3.1.0版本开始引入。5.0版本的并行索引扫描支持了分区表,提升了部分场景的性能。

openGauss只支持并行的segscan,通过在优化器中根据并行度直接计算每个线程要访问的页面号码,然后每个线程直接扫描对应的页面。在包含约束条件的扫描中,只能用并行segscan然后进行条件过滤或者是单线程的索引扫描,性能很低。

MogDB通过将查询任务分解为多个并行的子任务,同时扫描多个索引,可以避免扫描全部数据文件,提高查询效率,加快数据访问速度。使用并行索引扫描特性可以预计获得大约25%左右的性能提升,而对于整体执行来说,预计可以获得大约10%左右的性能提升。

image.png
索引并行扫描原理:

  • 1.多个线程同步对btree进行扫描,根据约束条件找到起始付置,各线程交替进行indexpage的获取和读取;
  • 2.各线程根据获得的indextuple来进行数据tuple的获取,各线程不需要同步,并行执行,加快数据访问速度。

测试验证

  • GLOBAL索引

    -- 1. 创建分区表,并插入数据。
    CREATE TABLE parallel_partition_index_01
    (
      c1 int,
      c2 int,
      c3 int
    )
    PARTITION BY RANGE(c1)
    (
      PARTITION P1 VALUES LESS THAN(2000),
      PARTITION P2 VALUES LESS THAN(4000),
      PARTITION P3 VALUES LESS THAN(6000),
      PARTITION P4 VALUES LESS THAN(MAXVALUE)
    )enable row movement;
    INSERT INTO parallel_partition_index_01 VALUES (generate_series(1, 10000), generate_series(1,10000), generate_series(1, 10000));
    
    -- 2. 创建索引。
    CREATE INDEX index_parallel_partition_index_01 on parallel_partition_index_01(c1) GLOBAL;
    
    -- 3. 关闭其他扫描类型,如seqscan、bitmapscan、indexonlyscan等。
    SET enable_seqscan = OFF;
    SET enable_bitmapscan = OFF;
    SET enable_indexonlyscan = OFF;
    
    -- 4. 打开并行开关,设置线程之间通信同步代价(smp_thread_cost)。
    -- 说明: smp_thread_cost参数值调低可以促使优化器优先选择并行。
    SET query_dop = 2;
    SET smp_thread_cost = 0;
    
    -- 5. 执行查询操作。
    SELECT * FROM parallel_partition_index_01 WHERE c1=100;
     c1  | c2  | c3  
    -----+-----+-----
     100 | 100 | 100
    (1 row)
    
    -- 6. 执行EXPLAIN语句查看执行计划信息。
    EXPLAIN (COSTS OFF) SELECT * FROM parallel_partition_index_01 WHERE c1<1000;
                                         QUERY PLAN                                        
    -----------------------------------------------------------------------------------------
     Streaming(type: LOCAL GATHER dop: 1/2)
     ->  Index Scan using index_parallel_partition_index_01 on parallel_partition_index_01
           Index Cond: (c1 < 1000)
    (3 rows)
  • LOCAL索引

    -- 1. 创建分区表,并插入数据。
    CREATE TABLE parallel_partition_index_01
    (
      c1 int,
      c2 int,
      c3 int
    )
    PARTITION BY RANGE(c1)
    (
      PARTITION P1 VALUES LESS THAN(2000),
      PARTITION P2 VALUES LESS THAN(4000),
      PARTITION P3 VALUES LESS THAN(6000),
      PARTITION P4 VALUES LESS THAN(MAXVALUE)
    )enable row movement;
    INSERT INTO parallel_partition_index_01 VALUES (generate_series(1, 10000), generate_series(1,10000), generate_series(1, 10000));
    
    -- 2. 创建索引。
    CREATE INDEX index_parallel_partition_index_01 on parallel_partition_index_01(c1) LOCAL;
    
    -- 3. 关闭其他扫描类型,如seqscan、bitmapscan、indexonlyscan等。
    SET enable_seqscan = OFF;
    SET enable_bitmapscan = OFF;
    SET enable_indexonlyscan = OFF;
    
    -- 4. 打开并行开关,设置线程之间通信同步代价(smp_thread_cost)。
    --说明:smp_thread_cost参数值调低可以促使优化器优先选择并行。
    SET query_dop = 2;
    SET smp_thread_cost = 0;
    
    -- 5. 执行查询操作。
    SELECT * FROM parallel_partition_index_01 WHERE c1=100;
     c1  | c2  | c3  
    -----+-----+-----
     100 | 100 | 100
    (1 row)
    
    -- 6. 执行EXPLAIN语句查看执行计划信息。
    EXPLAIN (COSTS OFF) SELECT * FROM parallel_partition_index_01 WHERE c1<1000;
                                          QUERY PLAN                                                 
    -----------------------------------------------------------------------------------------
     Streaming(type: LOCAL GATHER dop: 1/2)
     -> Partition Iterator
          Iterations: 1
          Selected Partitions:  1
          ->  Partitioned Index Scan using index_parallel_partition_index_01 on parallel_partition_index_01
                 Index Cond: (c1 < 1000)
    (6 rows)
    
    -- 7.开启enable_bitmapscan
    MogDB=# set enable_bitmapscan=on;
    SET
    
    --8.说明支持bitmapscan索引并行扫描。
    MogDB=# EXPLAIN (COSTS OFF) SELECT * FROM parallel_partition_index_01 WHERE c1<1000;
                                        QUERY PLAN                                      
    --------------------------------------------------------------------------------------
     Streaming(type: LOCAL GATHER dop: 1/2)
     ->  Partition Iterator
           Iterations: 1
           Selected Partitions:  1
           ->  Partitioned Bitmap Heap Scan on parallel_partition_index_01
                 Recheck Cond: (c1 < 1000)
                 ->  Partitioned Bitmap Index Scan on index_parallel_partition_index_01
                       Index Cond: (c1 < 1000)
    
    --9.开启indexonlyscan扫描类型
    SET enable_seqscan = OFF;
    SET enable_bitmapscan = OFF;
    set enable_indexscan=off;
    SET enable_indexonlyscan = on;
    
    --10.说明支持indexonlyscan索引并行扫描。
    MogDB=# EXPLAIN (COSTS OFF) SELECT c1 FROM parallel_partition_index_01 ;
                                                     QUERY PLAN                                                   
    ----------------------------------------------------------------------------------------------------------------
     Streaming(type: LOCAL GATHER dop: 1/2)
     ->  Partition Iterator
           Iterations: 4
           Selected Partitions:  1..4
           ->  Partitioned Index Only Scan using index_parallel_partition_index_01 on parallel_partition_index_01
    (5 rows)

    知识总结

    主要包含三种方式:indexscan、indexonlyscan以及bitmapscan。

  • indexscan:在对数据表进行范围查询时,可以通过索引定位到起始和结束位置,先扫描索引数据,再根据扫描结果对数据文件进行并行扫描,提升查询效率。
  • indexonlyscan:在进行表扫描时,当目标列都包含在索引中时,可以仅扫描索引数据,减少需要扫描的文件,同时可根据约束条件来对确定范围的索引数据进行并行扫描。
  • bitmapscan:在进行表扫描时,将索引扫描分为两个阶段。先并行扫描索引文件,获取要扫描的所有数据文件页;然后再并行扫描数据文件页,这样可以减少数据文件的随机访问和读取次数。

技术限制

本文由mdnice多平台发布


老许的数据库
1 声望0 粉丝

云和恩墨资深Oracledba,有12年左右的金融、保险、政府、地税、运营商等业务关键型系统的运维经验,曾担任公司异常恢复东区接口人,负责紧急异常恢复工作,目前负责pg、openGauss/MogDB运维、国产化 MogDB 数据库...