
# Partition Iterator
#### 算子说明
表分区技术（Table-Partitioning）通过将非常大的表或者索引从逻辑上切分为更小、更易管理的逻辑单元（分区），能够减小用户对表查询、变更等语句操作的影响范围；能够让用户通过分区键（Partition Key）快速定位到数据所在的分区，从而避免在数据库中对大表的全量扫描，能够在不同的分区上并发进行DDL、DML操作。GaussDB支持三种分区策略 ：范围分区、哈希分区、列表分区。范围分区基于二分binary-search实现，复杂度为O(logN)；哈希分区和列表分区基于key-partOid哈希表实现，复杂度为O(1)。
#### 典型场景
- 使用范围分区创建二级分区表。
- 使用哈希分区创建二级分区表。
- 使用列表分区创建二级分区表。
 
#### 示例
**示例1：**使用范围分区创建二级分区表。
```
--数据准备。 
gaussdb=# CREATE TABLE t1 (c1 int, c2 int) PARTITION BY RANGE (c1) SUBPARTITION BY RANGE (c1)
(
    PARTITION p1 VALUES LESS THAN(10) 
    (
        SUBPARTITION subp1_1 VALUES LESS THAN(5),
        SUBPARTITION subp1_2 VALUES LESS THAN(10)
    ),
    PARTITION p2 VALUES LESS THAN(20)
    (
        SUBPARTITION subp2_1 VALUES LESS THAN(15),
        SUBPARTITION subp2_2 VALUES LESS THAN(20)
    ),
    PARTITION p3 VALUES LESS THAN(MAXVALUE)
    (
        SUBPARTITION subp3_1 VALUES LESS THAN(30),
        SUBPARTITION subp3_2 VALUES LESS THAN(MAXVALUE)
    )
);
CREATE TABLE 
gaussdb=# INSERT INTO t1 VALUES(generate_series(1,100,2), 1);
INSERT 0 50
gaussdb=# NSERT INTO t1 VALUES(generate_series(2,101,2), 2);
INSERT 0 50
--执行结果。 
gaussdb=# EXPLAIN SELECT * FROM t1 WHERE c1 < 15 AND c2 <= 1;
                              QUERY PLAN                               
-----------------------------------------------------------------------
 Partition Iterator  (cost=0.00..33.23 rows=239 width=8)
   Iterations: 2, Sub Iterations: 3
   ->  Partitioned Seq Scan on t1  (cost=0.00..33.23 rows=239 width=8)
         Filter: ((c1 < 15) AND (c2 <= 1))
         Selected Partitions:  1..2
         Selected Subpartitions:  1:1..2  2:1
(6 rows))
--删除。
gaussdb=# DROP TABLE t1;
```
上述示例中，Partition Iterator算子输出信息如下所示。
| 信息名称                   | 含义                                                                                                                                                                                           |
|:---|:---|
| Partition Iterator     | 算子的名称。                                                                                                                                                                                       |
| Iterations             | 分区迭代算子对一级分区的迭代次数。如果显示PART则为动态剪枝场景。示例1中Iterations: 2 表示迭代算子需要遍历2个一级分区。Iterations: PART表示遍历一级分区个数需要由分区键上的参数条件决定。                                                                               |
| Sub Iterations         | 分区迭代算子对二级分区的迭代次数。如果显示PART则为动态剪枝场景。 示例1中Sub Iterations: 3表示迭代算子需要遍历3个二级分区。Iterations: PART表示遍历二级分区个数需要由分区键上的参数条件决定。 |
| Filter                 | 该算子的过滤谓词，示例中的过滤条件为C1列的值小于15，且c2列的值小于等于1。在查询执行时，满足这些条件的行会被包含在最终的结果集中。                                                                                                                         |
| Partitioned Seq Scan   | 分区表的扫描方式。                                                                                                                                                                                    |
| Selected Partitions    | 一级分区剪枝的结果。示例1中Selected Partitions: 1..2 代表1、2分区被选中。                                                                                                                                          |
| Selected Subpartitions | 二级分区剪枝的结果。示例1中Selected Subpartitions: 1:1..2 2:1 代表第一个一级分区的1、2号两个子分区 和 第二个一级分区的第1号分区被选中。Selected Subpartitions: ALL表示所有二级分区均被选中。                                                             |
   
**示例2：**使用哈希分区创建二级分区表。
```
--数据准备。 
gaussdb=#  CREATE TABLE sales (id INT,number INT) 
PARTITION BY HASH (number) 
SUBPARTITION BY HASH (id)
(
    PARTITION p0 
    (
        SUBPARTITION sp0_0,
        SUBPARTITION sp0_1
    ),
    PARTITION p1
    (
        SUBPARTITION sp1_0,
        SUBPARTITION sp1_1
    )
);
CREATE TABLE 
gaussdb=# INSERT INTO sales VALUES(generate_series(1,50), generate_series(1,50));
INSERT 0 50
--执行结果。 
gaussdb=# EXPLAIN SELECT * FROM sales WHERE id < 15 AND number <= 50;
                                QUERY PLAN                                
--------------------------------------------------------------------------
 Partition Iterator  (cost=0.00..42.23 rows=239 width=8)
   Iterations: 2, Sub Iterations: 4
   ->  Partitioned Seq Scan on sales  (cost=0.00..42.23 rows=239 width=8)
         Filter: ((id < 15) AND ("number" <= 50))
         Selected Partitions:  1..2
         Selected Subpartitions:  ALL
(6 rows)
--删除。
gaussdb=# DROP TABLE sales;
```
上述示例中，Partition Iterator算子输出信息如下所示。
| 信息名称                   | 含义                                                                                                                                                                                           |
|:---|:---|
| Partition Iterator     | 算子的名称。                                                                                                                                                                                       |
| Iterations             | 分区迭代算子对一级分区的迭代次数。如果显示PART则为动态剪枝场景。示例2中Iterations: 2 表示迭代算子需要遍历2个一级分区。Iterations: PART表示遍历一级分区个数需要由分区键上的参数条件决定。                                                                               |
| Sub Iterations         | 分区迭代算子对二级分区的迭代次数。如果显示PART则为动态剪枝场景。 示例2中Sub Iterations: 4表示迭代算子需要遍历4个二级分区。Iterations: PART表示遍历二级分区个数需要由分区键上的参数条件决定。 |
| Filter                 | 该算子的过滤谓词，示例2中的过滤条件为id列的值小于15，且number列的值小于等于50。在查询执行时，满足这些条件的行会被包含在最终的结果集中。                                                                                                                   |
| Partitioned Seq Scan   | 分区表的扫描方式。                                                                                                                                                                                    |
| Selected Partitions    | 一级分区剪枝的结果。示例2中Selected Partitions: 1..2 代表1、2分区被选中。                                                                                                                                          |
| Selected Subpartitions | 二级分区剪枝的结果。示例2中Selected Subpartitions: ALL表示所有二级分区均被选中。                                                                                                                                       |
   
**示例3：**使用列表分区创建二级分区表。
```
--数据准备。 
gaussdb=# CREATE TABLE list_partitioned_table (id INT,category INT) 
PARTITION BY LIST (category) 
SUBPARTITION BY LIST (id) 
(
    PARTITION p0 VALUES (1, 3, 5, 7)
    (
        SUBPARTITION sp0_0 VALUES (0),
        SUBPARTITION sp0_1 VALUES (1)
    ),
    PARTITION p1 VALUES (2, 4, 6, 8)
    (
        SUBPARTITION sp1_0 VALUES (0),
        SUBPARTITION sp1_1 VALUES (1)
    )
);
CREATE TABLE 
gaussdb=# INSERT INTO list_partitioned_table VALUES(0,generate_series(1,8,2));
INSERT 0 4
gaussdb=# INSERT INTO list_partitioned_table VALUES(1,generate_series(2,7,2));
INSERT 0 3
--执行结果。 
gaussdb=# EXPLAIN SELECT * FROM list_partitioned_table WHERE id = 0 AND category <= 5;
                                       QUERY PLAN                                        
-----------------------------------------------------------------------------------------
 Partition Iterator  (cost=0.00..42.23 rows=4 width=8)
   Iterations: 2, Sub Iterations: 2
   ->  Partitioned Seq Scan on list_partitioned_table  (cost=0.00..42.23 rows=4 width=8)
         Filter: ((category <= 5) AND (id = 0))
         Selected Partitions:  1..2
         Selected Subpartitions:  1:1  2:1
(6 rows) 
--删除。
gaussdb=# DROP TABLE list_partitioned_table;
```
上述示例中，Partition Iterator算子输出信息如下所示。
| 信息名称                   | 含义                                                                                                                                                                                           |
|:---|:---|
| Partition Iterator     | 算子的名称。                                                                                                                                                                                       |
| Iterations             | 分区迭代算子对一级分区的迭代次数。如果显示PART则为动态剪枝场景。示例3中Iterations: 2 表示迭代算子需要遍历2个一级分区。Iterations: PART表示遍历一级分区个数需要由分区键上的参数条件决定。                                                                               |
| Sub Iterations         | 分区迭代算子对二级分区的迭代次数。如果显示PART则为动态剪枝场景。 示例3中Sub Iterations: 2表示迭代算子需要遍历2个二级分区。Iterations: PART表示遍历二级分区个数需要由分区键上的参数条件决定。 |
| Filter                 | 该算子的过滤谓词，示例2中的过滤条件为category列的值小于等于5，且id列的值等于0。在查询执行时，满足这些条件的行会被包含在最终的结果集中。                                                                                                                   |
| Partitioned Seq Scan   | 分区表的扫描方式。                                                                                                                                                                                    |
| Selected Partitions    | 一级分区剪枝的结果。示例3中Selected Partitions: 1..2 代表1、2分区被选中。                                                                                                                                          |
| Selected Subpartitions | 二级分区剪枝的结果。示例3中Selected Subpartitions: 1:1 2:1 代表第一个一级分区的1号子分区 和 第二个一级分区的第1号子分区被选中。Selected Subpartitions: ALL表示所有二级分区均被选中。                                                                   |
   
