根据表大小或代价控制是否使用ePQ

PolarDB PostgreSQL版支持根据表的大小或执行计划的代价来控制对查询使用ePQ还是单机执行。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

PostgreSQL 14(内核小版本14.9.15.0及以上)。

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本的版本号:

select version();

背景信息

ePQ善于解决复杂、执行时间长的OLAP长查询,不适用于简单、执行时间短的OLTP短查询。对于短查询而言,计算节点之间建立连接、数据交换、销毁连接的开销反而会导致性能下降。PolarDB PostgreSQL版支持根据表的大小或执行计划的代价来控制对查询使用ePQ还是单机执行,从而在查询不同大小的表和执行不同代价的计划时,能够选择性能更好的查询执行方式。

注意事项

执行计划代价阈值和表大小阈值目前仅支持以下对象或操作:

  • 普通表

  • 分区表

  • 物化视图

  • 不带有ePQ的 hint/*+ PX() */的查询

参数说明

参数

说明

polar_px_min_pg_plan_cost

表示启用ePQ的执行计划代价最小值,取值范围:0~999999999999,默认值为50000。单机执行计划代价低于该阈值的查询将不会使用ePQ。

polar_px_min_table_scan_size

表示启用ePQ的最小表大小,取值范围:0~2147483647,默认值为100 MB。当查询中引用的所有表的大小都低于该阈值时,将不会使用ePQ。

polar_px_force_use

表示是否强制使用ePQ进行查询,取值如下:

  • on:强制使用ePQ进行查询。

  • off(默认):不强制使用ePQ进行查询。

使用指南

  1. 准备数据。

    CREATE TABLE test (id INT);
    INSERT INTO test SELECT generate_series(1, 1000);
    ANALYZE test;
  2. 查看执行计划代价。

    显式关闭ePQ,查看单机执行计划。

    SET polar_enable_px TO OFF;
    EXPLAIN SELECT COUNT(*) FROM test;
                              QUERY PLAN
    --------------------------------------------------------------
     Aggregate  (cost=17.50..17.51 rows=1 width=8)
       ->  Seq Scan on test  (cost=0.00..15.00 rows=1000 width=0)
    (2 rows)

    在上述执行计划中,每一行内的cost=xxx..xxx表示当前算子的估算执行代价,..前面的为启动代价,后面的为总代价。最顶层算子的总代价可以被认为是这条查询的总执行代价。例如,上述执行计划中的17.51即为总执行代价。由于单机执行计划的总代价低于参数polar_px_min_pg_plan_cost所指定的最小执行计划代价,所以即使开启ePQ,这条查询也不会使用ePQ。

    SET polar_enable_px TO ON;
    EXPLAIN SELECT COUNT(*) FROM test;
                              QUERY PLAN
    --------------------------------------------------------------
     Aggregate  (cost=17.50..17.51 rows=1 width=8)
       ->  Seq Scan on test  (cost=0.00..15.00 rows=1000 width=0)
    (2 rows)
  3. 查看表大小。

    通过函数pg_relation_size查看表的大小。

    SELECT pg_size_pretty(pg_relation_size('test'));
     pg_size_pretty
    ----------------
     40 kB
    (1 row)

    上述结果显示test表的大小为40 kB,低于polar_px_min_table_scan_size所指定的最小表大小,所以即使开启ePQ,任何只引用test表的查询都不会使用ePQ。

    SET polar_enable_px TO ON;
    EXPLAIN SELECT COUNT(*) FROM test AS a, test AS b, test AS c WHERE a.id > b.id AND b.id > c.id;
                                        QUERY PLAN
    ----------------------------------------------------------------------------------
     Aggregate  (cost=5292822.50..5292822.51 rows=1 width=8)
       ->  Nested Loop  (cost=0.00..5015045.00 rows=111111000 width=0)
             Join Filter: (b.id > c.id)
             ->  Nested Loop  (cost=0.00..15032.50 rows=333333 width=4)
                   Join Filter: (a.id > b.id)
                   ->  Seq Scan on test a  (cost=0.00..15.00 rows=1000 width=4)
                   ->  Materialize  (cost=0.00..20.00 rows=1000 width=4)
                         ->  Seq Scan on test b  (cost=0.00..15.00 rows=1000 width=4)
             ->  Materialize  (cost=0.00..20.00 rows=1000 width=4)
                   ->  Seq Scan on test c  (cost=0.00..15.00 rows=1000 width=4)
    (10 rows)
  4. 取消阈值。

    如果想要忽略执行计划代价阈值和表大小阈值,强行让查询使用ePQ,可以通过设置参数polar_px_force_use实现。

    SET polar_enable_px TO ON;
    SET polar_px_force_use TO ON;
    EXPLAIN SELECT COUNT(*) FROM test;
                                         QUERY PLAN
    -------------------------------------------------------------------------------------
     Finalize Aggregate  (cost=0.00..431.00 rows=1 width=8)
       ->  PX Coordinator 6:1  (slice1; segments: 6)  (cost=0.00..431.00 rows=1 width=8)
             ->  Partial Aggregate  (cost=0.00..431.00 rows=1 width=8)
                   ->  Partial Seq Scan on test  (cost=0.00..431.00 rows=167 width=1)
     Optimizer: PolarDB PX Optimizer
    (5 rows)
  5. 插入数据后重新执行计划代价。

    向表中再插入一定量的数据,使其满足启用ePQ的条件。

    INSERT INTO test SELECT generate_series(1, 10000000);
    ANALYZE test;

    此时,test表的大小已经超过了polar_px_min_table_scan_size所指定的最小表大小。

    SELECT pg_size_pretty(pg_relation_size('test'));
     pg_size_pretty
    ----------------
     348 MB
    (1 row)

    如下查询的单机执行计划代价也超过了polar_px_min_pg_plan_cost所指定的最小执行计划代价。

    SET polar_enable_px TO OFF;
    EXPLAIN SELECT COUNT(*) FROM test;
                                           QUERY PLAN
    -----------------------------------------------------------------------------------------
     Finalize Aggregate  (cost=97621.42..97621.43 rows=1 width=8)
       ->  Gather  (cost=97621.21..97621.42 rows=2 width=8)
             Workers Planned: 2
             ->  Partial Aggregate  (cost=96621.21..96621.22 rows=1 width=8)
                   ->  Parallel Seq Scan on test  (cost=0.00..86205.77 rows=4166177 width=0)
    (5 rows)

    开启ePQ,上述查询将会通过ePQ执行。

    SET polar_enable_px TO ON;
    SET polar_px_force_use TO OFF;
    EXPLAIN SELECT COUNT(*) FROM test;
                                          QUERY PLAN
    --------------------------------------------------------------------------------------
     Finalize Aggregate  (cost=0.00..470.76 rows=1 width=8)
       ->  PX Coordinator 6:1  (slice1; segments: 6)  (cost=0.00..470.76 rows=1 width=8)
             ->  Partial Aggregate  (cost=0.00..470.76 rows=1 width=8)
                   ->  Partial Seq Scan on test  (cost=0.00..467.66 rows=1666471 width=1)
     Optimizer: PolarDB PX Optimizer
    (5 rows)