Updated on 2024-05-20 GMT+08:00

Static Partition Pruning

For partitioned table query statements with constants in the search criteria, the search criteria contained in operators such as index scan, bitmap index scan, and index-only scan are used as pruning conditions in the optimizer phase to filter partitions. The search criteria must contain at least one partition key. For a partitioned table with a multi-column partition key, the search criteria can contain any column of the partition key.

Static pruning is supported in the following scenarios:
  1. Supported partitioning levels: level-1 partition and level-2 partition.
  2. Supported partitioning types: range partitioning, interval partitioning, hash partitioning, and list partitioning.
  3. Supported expression types: comparison expression (<, <=, =, >=, >), logical expression, and array expression.
  • Currently, static pruning does not support subquery expressions.
  • Query statements that specify level-1 partitions in level-2 partitioned tables cannot prune the filter conditions of the level-2 partition keys.
  • To support partitioned table pruning, the filter condition on the partition key is forcibly converted to the partition key type when the plan is generated. This operation is different from the implicit type conversion rule. As a result, an error may be reported when the same condition is converted on the partition key, and no error is reported for non-partition keys.
  • Typical scenarios where static pruning is supported are as follows:
    1. Comparison expressions
      -- Create a partitioned table.
      gaussdb=# CREATE TABLE t1 (c1 int, c2 int)
      PARTITION BY RANGE (c1)
      (
          PARTITION p1 VALUES LESS THAN(10),
          PARTITION p2 VALUES LESS THAN(20),
          PARTITION p3 VALUES LESS THAN(MAXVALUE)
      );
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = 1;
                     QUERY PLAN                
      -----------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 = 1)
               Selected Partitions:  1
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 < 1;
                     QUERY PLAN                
      -----------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 < 1)
               Selected Partitions:  1
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 > 11;
                     QUERY PLAN                
      -----------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 2
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 > 11)
               Selected Partitions:  2..3
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 is NULL;
                     QUERY PLAN                
      -----------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 IS NULL)
               Selected Partitions:  3
      (7 rows)
    2. Logical expressions
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = 1 AND c2 = 2;
                        QUERY PLAN                   
      -----------------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: ((t1.c1 = 1) AND (t1.c2 = 2))
               Selected Partitions:  1
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = 1 OR c1 = 2;
                        QUERY PLAN                  
      ----------------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: ((t1.c1 = 1) OR (t1.c1 = 2))
               Selected Partitions:  1
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE NOT c1 = 1;
                     QUERY PLAN                
      -----------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 3
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 <> 1)
               Selected Partitions:  1..3
      (7 rows)
    3. Array expressions
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 IN (1, 2, 3);
                            QUERY PLAN                      
      ------------------------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 = ANY ('{1,2,3}'::integer[]))
               Selected Partitions:  1
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = ALL(ARRAY[1, 2, 3]);
                            QUERY PLAN                      
      ------------------------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 0
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 = ALL ('{1,2,3}'::integer[]))
               Selected Partitions:  NONE
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = ANY(ARRAY[1, 2, 3]);
                            QUERY PLAN                      
      ------------------------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 = ANY ('{1,2,3}'::integer[]))
               Selected Partitions:  1
      (7 rows)
      
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = SOME(ARRAY[1, 2, 3]);
                            QUERY PLAN                      
      ------------------------------------------------------
       Partition Iterator
         Output: c1, c2
         Iterations: 1
         ->  Partitioned Seq Scan on public.t1
               Output: c1, c2
               Filter: (t1.c1 = ANY ('{1,2,3}'::integer[]))
               Selected Partitions:  1
      (7 rows)
  • Typical scenarios where static pruning is not supported are as follows:
    1. Subquery expressions
      gaussdb=# EXPLAIN (VERBOSE ON, COSTS OFF) SELECT * FROM t1 WHERE c1 = ALL(SELECT c2 FROM t1 WHERE c1 > 10);
                               QUERY PLAN                          
      -------------------------------------------------------------
       Partition Iterator
         Output: public.t1.c1, public.t1.c2
         Iterations: 3
         ->  Partitioned Seq Scan on public.t1
               Output: public.t1.c1, public.t1.c2
               Filter: (SubPlan 1)
               Selected Partitions:  1..3
      (7 rows)
      
      -- Cleanup example
      gaussdb=# DROP TABLE t1;