首批通过分布式安全可靠测评,为关键业务系统打造
表扫描分区号不连续的原因
更新时间:2026-05-21 09:16
在某些 SQL 执行计划中,针对分区表的 TABLE SCAN 算子需要进行全表扫描时(如 rowkey 为两列时:range(MIN, MIN; MAX, MAX)),该算子需要扫描的分区的分区号 partitions 不连续(如:partitions(p[0-1], p[3-4])。
具体原因
TABLE SCAN 算子需要对分区表进行全表扫描时,待扫描分区的分区号不连续的原因是:中间的分区已被删除。
OceanBase 会对创建的分区表的所有分区标注分区号,分区号相对分区固定。只有一级分区时,分区号格式为 p0,p1...;有两级分区时,分区号格式为:p0sp1,p0sp2...p1sp0,p1sp1...。 TABLE SCAN 算子的 partitions 代表将要扫描的分区的分区号,若 SQL 执行计划中针对某分区表的 TABLE SCAN 算子要对该表进行全表扫描时,会扫描该表的所有分区。
当该分区表的某些分区为空时 由于 TABLE SCAN 算子的全表扫描会涉及该表的所有分区(包括空分区),此时该算子的扫描分区号 partitions 连续。优化器无法判断分区内容是否为空(即分区内包含数据为零行与否)。
当该分区表的中间分区被删除后 TABLE SCAN 算子的扫描分区号会在 partitions 中如实显示。由于中间的分区被删除,全表扫描时,该分区对应的分区号将不会出现在该算子的 partitions 中,此时该算子的扫描分区号 partitions 不再连续。
案例演示
创建表 t2。
CREATE TABLE t2( c1 int(11)DEFAULT NULL, c2 int(11)DEFAULT NULL )partition by range(c1) (partition pa0 values less than (100), partition pa1 values less than (200), partition pa2 values less than (300), partition pa3 values less than (400), partition pa4 values less than (500));往表 t2 内插入测试数据。
INSERT INTO t2 values (1,100); INSERT INTO t2 values (101,100); INSERT INTO t2 values (301,100); INSERT INTO t2 values (401,100);查看此时的执行计划。
obclient > EXPLAIN EXTENDED SELECT * from t2;返回结果如下:
| ==================================================== |ID|OPERATOR |NAME |EST. ROWS|COST| ---------------------------------------------------- |0 |PX COORDINATOR | |5 |47 | |1 | EXCHANGE OUT DISTR |:EX10000|5 |46 | |2 | PX PARTITION ITERATOR| |5 |46 | |3 | TABLE SCAN |t2 |5 |46 | ==================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t2.c1(0x7efdf15de7f0), t2.c2(0x7efdf15deae0))(0x7efdf163e130)]), filter(nil) 1 - output([INTERNAL_FUNCTION(t2.c1(0x7efdf15de7f0), t2.c2(0x7efdf15deae0))(0x7efdf163e130)]), filter(nil), dop=1 2 - output([t2.c1(0x7efdf15de7f0)], [t2.c2(0x7efdf15deae0)]), filter(nil), force partition granule, asc. 3 - output([t2.c1(0x7efdf15de7f0)], [t2.c2(0x7efdf15deae0)]), filter(nil), access([t2.c1(0x7efdf15de7f0)], [t2.c2(0x7efdf15deae0)]), partitions(p[0-4]), is_index_back=false, range_key([t2.c1(0x7efdf15de7f0)], [t2.__pk_increment(0x7efdf162dcb0)]), range(MIN,MIN ; MAX,MAX)always true查看 TABLE SCAN 算子下对应的分区号,发现此时分区号
partitions(p[0-4])为连续。删除中间分区。
obclient > ALTER TABLE t2 DROP PARTITION pa2;再次查看 TABLE SCAN 算子。
obclient > EXPLAIN EXTENDED SELECT * from t2;返回结果如下:
| ==================================================== |ID|OPERATOR |NAME |EST. ROWS|COST| ---------------------------------------------------- |0 |PX COORDINATOR | |4 |46 | |1 | EXCHANGE OUT DISTR |:EX10000|4 |46 | |2 | PX PARTITION ITERATOR| |4 |46 | |3 | TABLE SCAN |t2 |4 |46 | ==================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t2.c1(0x7efeba5927f0), t2.c2(0x7efeba592ae0))(0x7efeba5eff60)]), filter(nil) 1 - output([INTERNAL_FUNCTION(t2.c1(0x7efeba5927f0), t2.c2(0x7efeba592ae0))(0x7efeba5eff60)]), filter(nil), dop=1 2 - output([t2.c1(0x7efeba5927f0)], [t2.c2(0x7efeba592ae0)]), filter(nil), force partition granule, asc. 3 - output([t2.c1(0x7efeba5927f0)], [t2.c2(0x7efeba592ae0)]), filter(nil), access([t2.c1(0x7efeba5927f0)], [t2.c2(0x7efeba592ae0)]), partitions(p[0-1], p[3-4]), is_index_back=false, range_key([t2.c1(0x7efeba5927f0)], [t2.__pk_increment(0x7efeba5dfae0)]), range(MIN,MIN ; MAX,MAX)always true查看 TABLE SCAN 算子下对应的分区,发现此时分区号
partitions(p[0-1], p[3-4])变成了非连续。
适用版本
OceanBase 数据库 V2.x、V3.x 版本。