| -- TODO: incremental sort is turned off by default, because it may have |
| -- wrong result for some core case. Turn it on to run the existing tests |
| -- and minimize the difference from upstream. |
| set enable_incremental_sort=on; |
| -- |
| -- Tests on partition pruning (with ORCA) or constraint exclusion (with the |
| -- Postgres planner). These tests check that you get an "expected" plan, that |
| -- only scans the partitions that are needed. |
| -- |
| -- The "correct" plan for a given query depends a lot on the capabilities of |
| -- the planner and the rest of the system, so the expected output can need |
| -- updating, as the system improves. |
| -- |
| -- Create test table with two partitions, for values equal to '1' and values equal to '2'. |
| create table parttab (n numeric, t text) |
| partition by list (n)(partition one values ('1'), partition two values('2')); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'n' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| -- Insert three rows. They're all equal to '1', but different number of zeros after decimal point. |
| insert into parttab values |
| ('1', 'one'), |
| ('1.0', 'one point zero'), |
| ('1.00', 'one point zero zero'); |
| -- select rows whose text representation is three characters long. This should return the '1.0' row. |
| select * from parttab where length(n::text) = 3; |
| n | t |
| -----+---------------- |
| 1.0 | one point zero |
| (1 row) |
| |
| explain select * from parttab where length(n::text) = 3; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=16) |
| -> Dynamic Seq Scan on parttab (cost=0.00..431.00 rows=1 width=16) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: (length((n)::text) = 3) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- Use index scans when possible. That exercises more code, and allows us to |
| -- spot the cases where the planner cannot use even when it exists. |
| set enable_seqscan=off; |
| set enable_bitmapscan=on; |
| set enable_indexscan=on; |
| create schema partition_pruning; |
| set search_path to partition_pruning; |
| -- Set up common test tables. |
| CREATE TABLE pt_lt_tab |
| ( |
| col1 int, |
| col2 decimal, |
| col3 text, |
| col4 bool |
| ) |
| distributed by (col1) |
| partition by list(col2) |
| ( |
| partition part1 values(1,2,3,4,5,6,7,8,9,10), |
| partition part2 values(11,12,13,14,15,16,17,18,19,20), |
| partition part3 values(21,22,23,24,25,26,27,28,29,30), |
| partition part4 values(31,32,33,34,35,36,37,38,39,40), |
| partition part5 values(41,42,43,44,45,46,47,48,49,50) |
| ); |
| INSERT INTO pt_lt_tab SELECT i, i,'a',True FROM generate_series(1,3)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'b',True FROM generate_series(4,6)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'c',True FROM generate_series(7,10)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'e',True FROM generate_series(11,13)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'f',True FROM generate_series(14,16)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'g',True FROM generate_series(17,20)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'i',False FROM generate_series(21,23)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'k',False FROM generate_series(24,26)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'h',False FROM generate_series(27,30)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'m',False FROM generate_series(31,33)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'o',False FROM generate_series(34,36)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'n',False FROM generate_series(37,40)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'p',False FROM generate_series(41,43)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'s',False FROM generate_series(44,46)i; |
| INSERT INTO pt_lt_tab SELECT i, i,'q',False FROM generate_series(47,50)i; |
| ANALYZE pt_lt_tab; |
| -- pt_lt_tab_df is the same as pt_lt_tab, but with a default partition (and some |
| -- values in the default partition, including NULLs). |
| CREATE TABLE pt_lt_tab_df |
| ( |
| col1 int, |
| col2 decimal, |
| col3 text, |
| col4 bool |
| ) |
| distributed by (col1) |
| partition by list(col2) |
| ( |
| partition part1 VALUES(1,2,3,4,5,6,7,8,9,10), |
| partition part2 VALUES(11,12,13,14,15,16,17,18,19,20), |
| partition part3 VALUES(21,22,23,24,25,26,27,28,29,30), |
| partition part4 VALUES(31,32,33,34,35,36,37,38,39,40), |
| partition part5 VALUES(41,42,43,44,45,46,47,48,49,50), |
| default partition def |
| ); |
| INSERT INTO pt_lt_tab_df SELECT i, i,'a',True FROM generate_series(1,3)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'b',True FROM generate_series(4,6)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'c',True FROM generate_series(7,10)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'e',True FROM generate_series(11,13)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'f',True FROM generate_series(14,16)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'g',True FROM generate_series(17,20)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'i',False FROM generate_series(21,23)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'k',False FROM generate_series(24,26)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'h',False FROM generate_series(27,30)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'m',False FROM generate_series(31,33)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'o',False FROM generate_series(34,36)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'n',False FROM generate_series(37,40)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'p',False FROM generate_series(41,43)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'s',False FROM generate_series(44,46)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'q',False FROM generate_series(47,50)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'u',True FROM generate_series(51,53)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'x',True FROM generate_series(54,56)i; |
| INSERT INTO pt_lt_tab_df SELECT i, i,'w',True FROM generate_series(57,60)i; |
| INSERT INTO pt_lt_tab_df VALUES(NULL,NULL,NULL,NULL); |
| INSERT INTO pt_lt_tab_df VALUES(NULL,NULL,NULL,NULL); |
| INSERT INTO pt_lt_tab_df VALUES(NULL,NULL,NULL,NULL); |
| ANALYZE pt_lt_tab_df; |
| -- |
| -- Test that stable functions are evaluated when constructing the plan. This |
| -- differs from PostgreSQL. In PostgreSQL, PREPARE/EXECUTE creates a reusable |
| -- plan, while in GPDB, we re-plan the query on every execution, so that the |
| -- stable function is executed during planning, and we can therefore do |
| -- partition pruning based on its result. |
| -- |
| create or replace function stabletestfunc() returns integer as $$ |
| begin |
| return 10; |
| end; |
| $$ language plpgsql stable; |
| PREPARE prep_prune AS select * from pt_lt_tab WHERE col2 = stabletestfunc(); |
| -- The plan should only scan one partition, where col2 = 10. |
| EXPLAIN EXECUTE prep_prune; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '10'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- Also test that Params are const-evaluated. |
| PREPARE prep_prune_param AS select * from pt_lt_tab WHERE col2 = $1; |
| EXPLAIN EXECUTE prep_prune_param(10); |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '10'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- @description B-tree single index key = non-partitioning key |
| CREATE INDEX idx1 on pt_lt_tab(col1); |
| SELECT * FROM pt_lt_tab WHERE col1 < 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 < 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Sort (cost=0.00..6.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=4 width=12) |
| Index Cond: (col1 < 10) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 > 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 > 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=1 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=1 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: (col1 > 50) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 = 25 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 25 | 25 | k | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 = 25 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=1 width=12) |
| -> Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=1 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: (col1 = 25) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 <> 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 <> 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=17 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=17 width=12) |
| Number of partitions to scan: 5 |
| Filter: (col1 <> 10) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 > 10 AND col1 < 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 > 10 AND col1 < 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.01 rows=2 width=12) |
| -> Sort (cost=0.00..6.01 rows=13 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=13 width=12) |
| Index Cond: ((col1 > 10) AND (col1 < 50)) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 > 10 OR col1 = 25 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 > 10 OR col1 = 25 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Sort (cost=0.00..431.00 rows=14 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=14 width=12) |
| Number of partitions to scan: 5 |
| Filter: ((col1 > 10) OR (col1 = 25)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 between 10 AND 25 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 10 | 10 | c | t |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 between 10 AND 25 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Sort (cost=0.00..6.00 rows=6 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=6 width=12) |
| Index Cond: ((col1 >= 10) AND (col1 <= 25)) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| DROP INDEX idx1; |
| -- @description B-tree single index key = partitioning key |
| CREATE INDEX idx1 on pt_lt_tab(col2); |
| SELECT * FROM pt_lt_tab WHERE col2 < 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 < 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Sort (cost=0.00..6.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=4 width=12) |
| Index Cond: (col2 < '10'::numeric) |
| Number of partitions to scan: 1 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------- |
| Limit (cost=0.00..0.00 rows=0 width=21) |
| -> Result (cost=0.00..0.00 rows=0 width=21) |
| -> Sort (cost=0.00..0.00 rows=0 width=21) |
| Sort Key: (NULL::numeric), (NULL::text) |
| -> Result (cost=0.00..0.00 rows=0 width=21) |
| One-Time Filter: false |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (7 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 = 25 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 25 | 25 | k | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 = 25 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: (col2 = '25'::numeric) |
| Number of partitions to scan: 1 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=16 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=16 width=12) |
| Number of partitions to scan: 5 |
| Filter: (col2 <> '10'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 10 AND col2 < 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 10 AND col2 < 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.01 rows=2 width=12) |
| -> Sort (cost=0.00..6.01 rows=12 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=13 width=12) |
| Index Cond: ((col2 > '10'::numeric) AND (col2 < '50'::numeric)) |
| Number of partitions to scan: 4 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 10 OR col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 10 OR col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Sort (cost=0.00..431.00 rows=13 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=13 width=12) |
| Number of partitions to scan: 4 |
| Filter: ((col2 > '10'::numeric) OR (col2 = '50'::numeric)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 between 10 AND 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 10 | 10 | c | t |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 between 10 AND 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.01 rows=2 width=12) |
| -> Sort (cost=0.00..6.01 rows=13 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=14 width=12) |
| Index Cond: ((col2 >= '10'::numeric) AND (col2 <= '50'::numeric)) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| DROP INDEX idx1; |
| -- @description multiple column b-tree index |
| CREATE INDEX idx1 on pt_lt_tab(col1,col2); |
| SELECT * FROM pt_lt_tab WHERE col1 < 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 < 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Sort (cost=0.00..6.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=4 width=12) |
| Index Cond: (col1 < 10) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col1 > 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col1 > 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=1 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=1 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: (col1 > 50) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 = 25 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 25 | 25 | k | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 = 25 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: (col2 = '25'::numeric) |
| Number of partitions to scan: 1 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=16 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=16 width=12) |
| Number of partitions to scan: 5 |
| Filter: (col2 <> '10'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 10 AND col1 = 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 10 AND col1 = 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=1 width=12) |
| -> Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=1 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: ((col1 = 10) AND (col2 > '10'::numeric)) |
| Number of partitions to scan: 4 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 10.00 OR col1 = 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 10.00 OR col1 = 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=14 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=14 width=12) |
| Number of partitions to scan: 5 |
| Filter: ((col2 > 10.00) OR (col1 = 50)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 between 10 AND 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 10 | 10 | c | t |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 between 10 AND 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.01 rows=2 width=12) |
| -> Sort (cost=0.00..6.01 rows=13 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.01 rows=14 width=12) |
| Index Cond: ((col2 >= '10'::numeric) AND (col2 <= '50'::numeric)) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| DROP INDEX idx1; |
| -- @description multi-column unique constraint (= b-tree index). Essentially the |
| -- same as the previous case, but the columns are the other way 'round, and we |
| -- do this on the table with default partition. |
| ALTER TABLE pt_lt_tab_df ADD CONSTRAINT col2_col1_unique unique(col2,col1); |
| SELECT * FROM pt_lt_tab_df WHERE col1 < 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col1 < 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Sort (cost=0.00..6.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on col2_col1_unique on pt_lt_tab_df (cost=0.00..6.00 rows=4 width=12) |
| Index Cond: (col1 < 10) |
| Number of partitions to scan: 6 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col1 > 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 51 | 51 | u | t |
| 52 | 52 | u | t |
| 53 | 53 | u | t |
| 54 | 54 | x | t |
| 55 | 55 | x | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col1 > 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Sort (cost=0.00..6.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on col2_col1_unique on pt_lt_tab_df (cost=0.00..6.00 rows=4 width=12) |
| Index Cond: (col1 > 50) |
| Number of partitions to scan: 6 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 = 25 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 25 | 25 | k | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 = 25 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on col2_col1_unique on pt_lt_tab_df (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: (col2 = '25'::numeric) |
| Number of partitions to scan: 1 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=20 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=20 width=12) |
| Number of partitions to scan: 6 |
| Filter: (col2 <> '10'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 > 10 AND col1 = 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 > 10 AND col1 = 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.00 rows=1 width=12) |
| -> Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=1 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..6.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on col2_col1_unique on pt_lt_tab_df (cost=0.00..6.00 rows=1 width=12) |
| Index Cond: ((col2 > '10'::numeric) AND (col1 = 10)) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 > 10.00 OR col1 = 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 > 10.00 OR col1 = 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=17 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=17 width=12) |
| Number of partitions to scan: 6 |
| Filter: ((col2 > 10.00) OR (col1 = 50)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 between 10 AND 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 10 | 10 | c | t |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 between 10 AND 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| -------------------------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.01 rows=2 width=12) |
| -> Sort (cost=0.00..6.01 rows=14 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on col2_col1_unique on pt_lt_tab_df (cost=0.00..6.01 rows=14 width=12) |
| Index Cond: ((col2 >= '10'::numeric) AND (col2 <= '50'::numeric)) |
| Number of partitions to scan: 6 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| ALTER TABLE pt_lt_tab_df DROP CONSTRAINT col2_col1_unique; |
| -- @description Heterogeneous index, index on partition key, b-tree index on all partitions |
| CREATE INDEX idx1 on pt_lt_tab_1_prt_part1(col2); |
| CREATE INDEX idx2 on pt_lt_tab_1_prt_part2(col2); |
| CREATE INDEX idx3 on pt_lt_tab_1_prt_part3(col2); |
| CREATE INDEX idx4 on pt_lt_tab_1_prt_part4(col2); |
| CREATE INDEX idx5 on pt_lt_tab_1_prt_part5(col2); |
| SELECT * FROM pt_lt_tab WHERE col2 between 1 AND 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 between 1 AND 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=16 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=16 width=12) |
| Number of partitions to scan: 5 |
| Filter: ((col2 >= '1'::numeric) AND (col2 <= '50'::numeric)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 5 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 6 | 6 | b | t |
| 7 | 7 | c | t |
| 8 | 8 | c | t |
| 9 | 9 | c | t |
| 10 | 10 | c | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 5 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| --------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Sort (cost=0.00..431.00 rows=14 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=14 width=12) |
| Number of partitions to scan: 5 |
| Filter: (col2 > '5'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 = 5 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 5 | 5 | b | t |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 = 5 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| -------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| Merge Key: pt_lt_tab_1_prt_part1.col2, pt_lt_tab_1_prt_part1.col3 |
| -> Sort (cost=0.00..431.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '5'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx2; |
| DROP INDEX idx3; |
| DROP INDEX idx4; |
| DROP INDEX idx5; |
| -- @description Heterogeneous index,b-tree index on all parts,index, index on non-partition col |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col1); |
| CREATE INDEX idx2 on pt_lt_tab_df_1_prt_part2(col1); |
| CREATE INDEX idx3 on pt_lt_tab_df_1_prt_part3(col1); |
| CREATE INDEX idx4 on pt_lt_tab_df_1_prt_part4(col1); |
| CREATE INDEX idx5 on pt_lt_tab_df_1_prt_part5(col1); |
| CREATE INDEX idx6 on pt_lt_tab_df_1_prt_def(col1); |
| SELECT * FROM pt_lt_tab_df WHERE col1 between 1 AND 100 ORDER BY col1 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col1 between 1 AND 100 ORDER BY col1 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col1 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=20 width=12) |
| Sort Key: col1 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=20 width=12) |
| Number of partitions to scan: 6 |
| Filter: ((col1 >= 1) AND (col1 <= 100)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col1 > 50 ORDER BY col1 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 51 | 51 | u | t |
| 52 | 52 | u | t |
| 53 | 53 | u | t |
| 54 | 54 | x | t |
| 55 | 55 | x | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col1 > 50 ORDER BY col1 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=12) |
| Merge Key: col1 |
| -> Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Sort (cost=0.00..431.00 rows=4 width=12) |
| Sort Key: col1 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=4 width=12) |
| Number of partitions to scan: 6 |
| Filter: (col1 > 50) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col1 < 50 ORDER BY col1 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col1 < 50 ORDER BY col1 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col1 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=17 width=12) |
| Sort Key: col1 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=17 width=12) |
| Number of partitions to scan: 6 |
| Filter: (col1 < 50) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx2; |
| DROP INDEX idx3; |
| DROP INDEX idx4; |
| DROP INDEX idx5; |
| DROP INDEX idx6; |
| -- @description Heterogeneous index,b-tree index on all parts including default, index on partition col |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col2); |
| CREATE INDEX idx2 on pt_lt_tab_df_1_prt_part2(col2); |
| CREATE INDEX idx3 on pt_lt_tab_df_1_prt_part3(col2); |
| CREATE INDEX idx4 on pt_lt_tab_df_1_prt_part4(col2); |
| CREATE INDEX idx5 on pt_lt_tab_df_1_prt_part5(col2); |
| CREATE INDEX idx6 on pt_lt_tab_df_1_prt_def(col2); |
| SELECT * FROM pt_lt_tab_df WHERE col2 between 1 AND 100 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 between 1 AND 100 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=20 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=20 width=12) |
| Number of partitions to scan: 6 |
| Filter: ((col2 >= '1'::numeric) AND (col2 <= '100'::numeric)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 > 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 51 | 51 | u | t |
| 52 | 52 | u | t |
| 53 | 53 | u | t |
| 54 | 54 | x | t |
| 55 | 55 | x | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 > 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=12) |
| Merge Key: pt_lt_tab_df_1_prt_def.col2, pt_lt_tab_df_1_prt_def.col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Sort (cost=0.00..431.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=4 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 > '50'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 50 | 50 | q | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..431.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '50'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 <> 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=20 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=20 width=12) |
| Number of partitions to scan: 6 |
| Filter: (col2 <> '10'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 between 1 AND 100 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 1 | 1 | a | t |
| 2 | 2 | a | t |
| 3 | 3 | a | t |
| 4 | 4 | b | t |
| 5 | 5 | b | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 between 1 AND 100 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=20 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=20 width=12) |
| Number of partitions to scan: 6 |
| Filter: ((col2 >= '1'::numeric) AND (col2 <= '100'::numeric)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 < 50 AND col1 > 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 < 50 AND col1 > 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=17 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=17 width=12) |
| Number of partitions to scan: 6 |
| Filter: ((col2 < '50'::numeric) AND (col1 > 10)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx2; |
| DROP INDEX idx3; |
| DROP INDEX idx4; |
| DROP INDEX idx5; |
| DROP INDEX idx6; |
| -- @description Negative tests Combination tests, no index on default partition |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col2); |
| CREATE INDEX idx2 on pt_lt_tab_df_1_prt_part2(col2); |
| CREATE INDEX idx3 on pt_lt_tab_df_1_prt_part3(col2); |
| CREATE INDEX idx4 on pt_lt_tab_df_1_prt_part4(col2); |
| CREATE INDEX idx5 on pt_lt_tab_df_1_prt_part5(col2); |
| SELECT * FROM pt_lt_tab_df WHERE col2 > 51 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 52 | 52 | u | t |
| 53 | 53 | u | t |
| 54 | 54 | x | t |
| 55 | 55 | x | t |
| 56 | 56 | x | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 > 51 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=12) |
| Merge Key: pt_lt_tab_df_1_prt_def.col2, pt_lt_tab_df_1_prt_def.col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Sort (cost=0.00..431.00 rows=4 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=4 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 > '51'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 50 | 50 | q | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..431.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '50'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx2; |
| DROP INDEX idx3; |
| DROP INDEX idx4; |
| DROP INDEX idx5; |
| -- @description Negative tests Combination tests ,index exists on some regular partitions and not on the default partition |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col2); |
| CREATE INDEX idx5 on pt_lt_tab_df_1_prt_part5(col2); |
| SELECT * FROM pt_lt_tab_df WHERE col2 is NULL ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| | | | |
| | | | |
| | | | |
| (3 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx5; |
| -- @description Heterogeneous index,b-tree index on all parts,index , multiple index |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col2,col1); |
| CREATE INDEX idx2 on pt_lt_tab_df_1_prt_part2(col2,col1); |
| CREATE INDEX idx3 on pt_lt_tab_df_1_prt_part3(col2,col1); |
| CREATE INDEX idx4 on pt_lt_tab_df_1_prt_part4(col2,col1); |
| CREATE INDEX idx5 on pt_lt_tab_df_1_prt_part5(col2,col1); |
| CREATE INDEX idx6 on pt_lt_tab_df_1_prt_def(col2,col1); |
| SELECT * FROM pt_lt_tab_df WHERE col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 50 | 50 | q | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 = 50 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..431.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '50'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col2 > 10 AND col1 between 1 AND 100 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 11 | 11 | e | t |
| 12 | 12 | e | t |
| 13 | 13 | e | t |
| 14 | 14 | f | t |
| 15 | 15 | f | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 > 10 AND col1 between 1 AND 100 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=17 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=17 width=12) |
| Number of partitions to scan: 5 |
| Filter: ((col2 > '10'::numeric) AND (col1 >= 1) AND (col1 <= 100)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab_df WHERE col1 = 10 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 10 | 10 | c | t |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col1 = 10 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..431.00 rows=2 width=12) |
| Merge Key: col2, col3 |
| -> Sort (cost=0.00..431.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 6 |
| Filter: (col1 = 10) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx2; |
| DROP INDEX idx3; |
| DROP INDEX idx4; |
| DROP INDEX idx5; |
| DROP INDEX idx6; |
| -- @description Index exists on some continuous set of partitions, e.g. p1,p2,p3 |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col2); |
| CREATE INDEX idx2 on pt_lt_tab_df_1_prt_part2(col2); |
| CREATE INDEX idx3 on pt_lt_tab_df_1_prt_part3(col2); |
| SELECT * FROM pt_lt_tab_df WHERE col2 = 35 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 35 | 35 | o | f |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 = 35 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=2 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=2 width=12) |
| Merge Key: pt_lt_tab_df_1_prt_part4.col2, pt_lt_tab_df_1_prt_part4.col3 |
| -> Sort (cost=0.00..431.00 rows=1 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=1 width=12) |
| Number of partitions to scan: 1 |
| Filter: (col2 = '35'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (9 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx2; |
| DROP INDEX idx3; |
| -- @description Index exists on some regular partitions and on the default partition [INDEX exists on non-consecutive partitions, e.g. p1,p3,p5] |
| CREATE INDEX idx1 on pt_lt_tab_df_1_prt_part1(col2); |
| CREATE INDEX idx5 on pt_lt_tab_df_1_prt_part5(col2); |
| CREATE INDEX idx6 on pt_lt_tab_df_1_prt_def(col2); |
| SELECT * FROM pt_lt_tab_df WHERE col2 > 15 ORDER BY col2,col3 LIMIT 5; |
| col1 | col2 | col3 | col4 |
| ------+------+------+------ |
| 16 | 16 | f | t |
| 17 | 17 | g | t |
| 18 | 18 | g | t |
| 19 | 19 | g | t |
| 20 | 20 | g | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab_df WHERE col2 > 15 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------ |
| Limit (cost=0.00..431.01 rows=5 width=12) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.01 rows=5 width=12) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.01 rows=2 width=12) |
| -> Sort (cost=0.00..431.01 rows=16 width=12) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab_df (cost=0.00..431.00 rows=16 width=12) |
| Number of partitions to scan: 5 |
| Filter: (col2 > '15'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| DROP INDEX idx1; |
| DROP INDEX idx5; |
| DROP INDEX idx6; |
| -- |
| -- Finally, after running all the other tests on pg_lt_tab, test that |
| -- partition pruning still works after dropping a column |
| -- |
| CREATE INDEX idx1 on pt_lt_tab(col4); |
| ALTER TABLE pt_lt_tab DROP column col1; |
| NOTICE: dropping a column that is part of the distribution policy forces a random distribution policy |
| NOTICE: dropping a column that is part of the distribution policy forces a random distribution policy |
| NOTICE: dropping a column that is part of the distribution policy forces a random distribution policy |
| NOTICE: dropping a column that is part of the distribution policy forces a random distribution policy |
| NOTICE: dropping a column that is part of the distribution policy forces a random distribution policy |
| NOTICE: dropping a column that is part of the distribution policy forces a random distribution policy |
| SELECT * FROM pt_lt_tab WHERE col4 is False ORDER BY col2,col3 LIMIT 5; |
| col2 | col3 | col4 |
| ------+------+------ |
| 21 | i | f |
| 22 | i | f |
| 23 | i | f |
| 24 | k | f |
| 25 | k | f |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col4 is False ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=8) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=8) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=8) |
| -> Sort (cost=0.00..431.00 rows=7 width=8) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=7 width=8) |
| Number of partitions to scan: 5 |
| Filter: (col4 IS FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col4 = False ORDER BY col2,col3 LIMIT 5; |
| col2 | col3 | col4 |
| ------+------+------ |
| 21 | i | f |
| 22 | i | f |
| 23 | i | f |
| 24 | k | f |
| 25 | k | f |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col4 = False ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..6.01 rows=5 width=8) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.01 rows=5 width=8) |
| Merge Key: col2, col3 |
| -> Limit (cost=0.00..6.01 rows=2 width=8) |
| -> Sort (cost=0.00..6.01 rows=10 width=8) |
| Sort Key: col2, col3 |
| -> Dynamic Index Scan on idx1 on pt_lt_tab (cost=0.00..6.00 rows=10 width=8) |
| Index Cond: (col4 = false) |
| Number of partitions to scan: 5 |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| SELECT * FROM pt_lt_tab WHERE col2 > 41 ORDER BY col2,col3 LIMIT 5; |
| col2 | col3 | col4 |
| ------+------+------ |
| 42 | p | f |
| 43 | p | f |
| 44 | s | f |
| 45 | s | f |
| 46 | s | f |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 41 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=8) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=8) |
| Merge Key: pt_lt_tab_1_prt_part5.col2, pt_lt_tab_1_prt_part5.col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=8) |
| -> Sort (cost=0.00..431.00 rows=4 width=8) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=4 width=8) |
| Number of partitions to scan: 1 |
| Filter: (col2 > '41'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| ALTER TABLE pt_lt_tab DROP column col4; |
| SELECT * FROM pt_lt_tab WHERE col2 > 41 ORDER BY col2,col3 LIMIT 5; |
| col2 | col3 |
| ------+------ |
| 42 | p |
| 43 | p |
| 44 | s |
| 45 | s |
| 46 | s |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_lt_tab WHERE col2 > 41 ORDER BY col2,col3 LIMIT 5; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------- |
| Limit (cost=0.00..431.00 rows=5 width=7) |
| -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=7) |
| Merge Key: pt_lt_tab_1_prt_part5.col2, pt_lt_tab_1_prt_part5.col3 |
| -> Limit (cost=0.00..431.00 rows=2 width=7) |
| -> Sort (cost=0.00..431.00 rows=4 width=7) |
| Sort Key: col2, col3 |
| -> Dynamic Seq Scan on pt_lt_tab (cost=0.00..431.00 rows=4 width=7) |
| Number of partitions to scan: 1 |
| Filter: (col2 > '41'::numeric) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (10 rows) |
| |
| -- |
| -- Test a more complicated partitioning scheme, with subpartitions. |
| -- |
| CREATE TABLE pt_complex (i int, j int, k int, l int, m int) DISTRIBUTED BY (i) |
| PARTITION BY list(k) |
| SUBPARTITION BY list(j) SUBPARTITION TEMPLATE (subpartition p11 values (1), subpartition p12 values(2)) |
| SUBPARTITION BY list(l) SUBPARTITION TEMPLATE (subpartition p11 values (1), subpartition p12 values(2)) |
| ( partition p1 values(1), partition p2 values(2)); |
| INSERT INTO pt_complex VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2); |
| CREATE INDEX i_pt_complex ON pt_complex (i); |
| SELECT * FROM pt_complex WHERE i = 1 AND j = 1; |
| i | j | k | l | m |
| ---+---+---+---+--- |
| 1 | 1 | 1 | 1 | 1 |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_complex WHERE i = 1 AND j = 1; |
| QUERY PLAN |
| -------------------------------------------------------------------------------------------------------------------------- |
| Gather Motion 1:1 (slice1; segments: 1) (cost=4.65..147.85 rows=12 width=20) |
| -> Append (cost=4.65..147.69 rows=4 width=20) |
| -> Bitmap Heap Scan on pt_complex_1_prt_p1_2_prt_p11_3_prt_p11 pt_complex_1 (cost=4.65..36.92 rows=1 width=20) |
| Recheck Cond: (i = 1) |
| Filter: (j = 1) |
| -> Bitmap Index Scan on pt_complex_1_prt_p1_2_prt_p11_3_prt_p11_i_idx (cost=0.00..4.65 rows=22 width=0) |
| Index Cond: (i = 1) |
| -> Bitmap Heap Scan on pt_complex_1_prt_p1_2_prt_p11_3_prt_p12 pt_complex_2 (cost=4.65..36.92 rows=1 width=20) |
| Recheck Cond: (i = 1) |
| Filter: (j = 1) |
| -> Bitmap Index Scan on pt_complex_1_prt_p1_2_prt_p11_3_prt_p12_i_idx (cost=0.00..4.65 rows=22 width=0) |
| Index Cond: (i = 1) |
| -> Bitmap Heap Scan on pt_complex_1_prt_p2_2_prt_p11_3_prt_p11 pt_complex_3 (cost=4.65..36.92 rows=1 width=20) |
| Recheck Cond: (i = 1) |
| Filter: (j = 1) |
| -> Bitmap Index Scan on pt_complex_1_prt_p2_2_prt_p11_3_prt_p11_i_idx (cost=0.00..4.65 rows=22 width=0) |
| Index Cond: (i = 1) |
| -> Bitmap Heap Scan on pt_complex_1_prt_p2_2_prt_p11_3_prt_p12 pt_complex_4 (cost=4.65..36.92 rows=1 width=20) |
| Recheck Cond: (i = 1) |
| Filter: (j = 1) |
| -> Bitmap Index Scan on pt_complex_1_prt_p2_2_prt_p11_3_prt_p12_i_idx (cost=0.00..4.65 rows=22 width=0) |
| Index Cond: (i = 1) |
| Optimizer: Postgres query optimizer |
| (23 rows) |
| |
| -- |
| -- See MPP-6861 |
| -- |
| CREATE TABLE ds_4 |
| ( |
| month_id character varying(6), |
| cust_group_acc numeric(10), |
| mobile_no character varying(10), |
| source character varying(12), |
| vas_group numeric(10), |
| vas_type numeric(10), |
| count_vas integer, |
| amt_vas numeric(10,2), |
| network_type character varying(3), |
| execution_id integer |
| ) |
| WITH ( |
| OIDS=FALSE |
| ) |
| DISTRIBUTED BY (cust_group_acc, mobile_no) |
| PARTITION BY LIST(month_id) |
| ( |
| PARTITION p200800 VALUES('200800'), |
| PARTITION p200801 VALUES('200801'), |
| PARTITION p200802 VALUES('200802'), |
| PARTITION p200803 VALUES('200803') |
| ); |
| -- this is the case that worked before MPP-6861 |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where month_id = '200800'; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 1 |
| Filter: ((month_id)::text = '200800'::text) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- now we can evaluate this function at planning/prune time |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where month_id::int = 200800; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: ((month_id)::integer = 200800) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- this will be satisfied by 200800 |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where month_id::int - 801 < 200000; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: (((month_id)::integer - 801) < 200000) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- test OR case -- should NOT get pruning |
| explain select * from ds_4 where month_id::int - 801 < 200000 OR count_vas > 10; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: ((((month_id)::integer - 801) < 200000) OR (count_vas > 10)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- test AND case -- should still get pruning |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where month_id::int - 801 < 200000 AND count_vas > 10; |
| QUERY PLAN |
| ------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: ((((month_id)::integer - 801) < 200000) AND (count_vas > 10)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- test expression case : should get pruning |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where case when month_id = '200800' then 100 else 2 end = 100; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: (CASE WHEN ((month_id)::text = '200800'::text) THEN 100 ELSE 2 END = 100) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- test expression case : should get pruning |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where case when month_id = '200800' then NULL else 2 end IS NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: (CASE WHEN ((month_id)::text = '200800'::text) THEN NULL::integer ELSE 2 END IS NULL) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- should still get pruning here -- count_vas is only used in the path for month id = 200800 |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where case when month_id::int = 200800 then count_vas else 2 end IS NULL; |
| QUERY PLAN |
| ---------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: (CASE WHEN ((month_id)::integer = 200800) THEN count_vas ELSE 2 END IS NULL) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- do one that matches a couple partitions |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_4 where month_id::int in (200801, 1,55,6,6,6,6,66,565,65,65,200803); |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| -> Dynamic Seq Scan on ds_4 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 4 |
| Filter: ((month_id)::integer = ANY ('{200801,1,55,6,6,6,6,66,565,65,65,200803}'::integer[])) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| -- cleanup |
| drop table ds_4; |
| -- |
| -- See MPP-18979 |
| -- |
| CREATE TABLE ds_2 |
| ( |
| month_id character varying(6), |
| cust_group_acc numeric(10), |
| mobile_no character varying(10), |
| source character varying(12), |
| vas_group numeric(10), |
| vas_type numeric(10), |
| count_vas integer, |
| amt_vas numeric(10,2), |
| network_type character varying(3), |
| execution_id integer |
| ) |
| WITH ( |
| OIDS=FALSE |
| ) |
| DISTRIBUTED BY (cust_group_acc, mobile_no) |
| PARTITION BY LIST(month_id) |
| ( |
| PARTITION p200800 VALUES('200800'), |
| PARTITION p200801 VALUES('200801'), |
| PARTITION p200802 VALUES('200802'), |
| PARTITION p200803 VALUES('200803'), |
| PARTITION p200804 VALUES('200804'), |
| PARTITION p200805 VALUES('200805'), |
| PARTITION p200806 VALUES('200806'), |
| PARTITION p200807 VALUES('200807'), |
| PARTITION p200808 VALUES('200808'), |
| PARTITION p200809 VALUES('200809') |
| ); |
| insert into ds_2(month_id) values('200800'); |
| insert into ds_2(month_id) values('200801'); |
| insert into ds_2(month_id) values('200802'); |
| insert into ds_2(month_id) values('200803'); |
| insert into ds_2(month_id) values('200804'); |
| insert into ds_2(month_id) values('200805'); |
| insert into ds_2(month_id) values('200806'); |
| insert into ds_2(month_id) values('200807'); |
| insert into ds_2(month_id) values('200808'); |
| insert into ds_2(month_id) values('200809'); |
| -- queries without bitmap scan |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| set optimizer_segments=2; |
| explain select * from ds_2 where month_id::int in (200808, 1315) order by month_id; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| Merge Key: month_id |
| -> Sort (cost=0.00..431.00 rows=1 width=71) |
| Sort Key: month_id |
| -> Dynamic Seq Scan on ds_2 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 10 |
| Filter: ((month_id)::integer = ANY ('{200808,1315}'::integer[])) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (8 rows) |
| |
| -- start_ignore |
| -- Known_opt_diff: MPP-21316 |
| -- end_ignore |
| explain select * from ds_2 where month_id::int in (200808, 200801, 2008010) order by month_id; |
| QUERY PLAN |
| ------------------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=71) |
| Merge Key: month_id |
| -> Sort (cost=0.00..431.00 rows=1 width=71) |
| Sort Key: month_id |
| -> Dynamic Seq Scan on ds_2 (cost=0.00..431.00 rows=1 width=71) |
| Number of partitions to scan: 10 |
| Filter: ((month_id)::integer = ANY ('{200808,200801,2008010}'::integer[])) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (8 rows) |
| |
| reset optimizer_segments; |
| select * from ds_2 where month_id::int in (200907, 1315) order by month_id; |
| month_id | cust_group_acc | mobile_no | source | vas_group | vas_type | count_vas | amt_vas | network_type | execution_id |
| ----------+----------------+-----------+--------+-----------+----------+-----------+---------+--------------+-------------- |
| (0 rows) |
| |
| select * from ds_2 where month_id::int in (200808, 1315) order by month_id; |
| month_id | cust_group_acc | mobile_no | source | vas_group | vas_type | count_vas | amt_vas | network_type | execution_id |
| ----------+----------------+-----------+--------+-----------+----------+-----------+---------+--------------+-------------- |
| 200808 | | | | | | | | | |
| (1 row) |
| |
| select * from ds_2 where month_id::int in (200808, 200801) order by month_id; |
| month_id | cust_group_acc | mobile_no | source | vas_group | vas_type | count_vas | amt_vas | network_type | execution_id |
| ----------+----------------+-----------+--------+-----------+----------+-----------+---------+--------------+-------------- |
| 200801 | | | | | | | | | |
| 200808 | | | | | | | | | |
| (2 rows) |
| |
| select * from ds_2 where month_id::int in (200808, 200801, 2008010) order by month_id; |
| month_id | cust_group_acc | mobile_no | source | vas_group | vas_type | count_vas | amt_vas | network_type | execution_id |
| ----------+----------------+-----------+--------+-----------+----------+-----------+---------+--------------+-------------- |
| 200801 | | | | | | | | | |
| 200808 | | | | | | | | | |
| (2 rows) |
| |
| -- cleanup |
| drop table ds_2; |
| drop table if exists dnsdata cascade; |
| NOTICE: table "dnsdata" does not exist, skipping |
| CREATE TABLE dnsdata(dnsname text) DISTRIBUTED RANDOMLY; |
| CREATE INDEX dnsdata_d1_idx ON dnsdata USING bitmap (split_part(reverse(dnsname),'.'::text,1)); |
| CREATE INDEX dnsdata_d2_idx ON dnsdata USING bitmap (split_part(reverse(dnsname),'.'::text,2)); |
| insert into dnsdata values('www.google.com'); |
| insert into dnsdata values('www.google1.com'); |
| insert into dnsdata values('1.google.com'); |
| insert into dnsdata values('2.google.com'); |
| insert into dnsdata select 'www.b.com' from generate_series(1, 100000) as x(a); |
| analyze dnsdata; |
| -- queries with bitmap scan enabled |
| set enable_bitmapscan=on; |
| set enable_indexscan=on; |
| set enable_seqscan=off; |
| Select dnsname from dnsdata |
| where (split_part(reverse('cache.google.com'),'.',1))=(split_part(reverse(dnsname),'.',1)) |
| and (split_part(reverse('cache.google.com'),'.',2))=(split_part(reverse(dnsname),'.',2)) |
| order by dnsname; |
| dnsname |
| ---------------- |
| 1.google.com |
| 2.google.com |
| www.google.com |
| (3 rows) |
| |
| Select dnsname from dnsdata |
| where (split_part(reverse('cache.google.com'),'.',1))=(split_part(reverse(dnsname),'.',1)) |
| and (split_part(reverse('cache.google.com'),'.',2))=(split_part(reverse(dnsname),'.',2)) |
| and dnsname = 'cache.google.com' |
| order by dnsname; |
| dnsname |
| --------- |
| (0 rows) |
| |
| -- cleanup |
| drop table dnsdata cascade; |
| Create or replace function ZeroFunc(int) Returns int as $BODY$ |
| BEGIN |
| RETURN 0; |
| END; |
| $BODY$ LANGUAGE plpgsql IMMUTABLE; |
| drop table if exists mytable cascade; |
| NOTICE: table "mytable" does not exist, skipping |
| create table mytable(i int, j int); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| insert into mytable select x, x+1 from generate_series(1, 100000) as x; |
| analyze mytable; |
| CREATE INDEX mytable_idx1 ON mytable USING bitmap(ZeroFunc(i)); |
| select * from mytable where ZeroFunc(i)=0 and i=100 order by i; |
| i | j |
| -----+----- |
| 100 | 101 |
| (1 row) |
| |
| select * from mytable where ZeroFunc(i)=0 and i=-1 order by i; |
| i | j |
| ---+--- |
| (0 rows) |
| |
| -- cleanup |
| drop function ZeroFunc(int) cascade; |
| NOTICE: drop cascades to index mytable_idx1 |
| drop table mytable cascade; |
| -- @description Tests for static partition selection (MPP-24709, GPSQL-2879) |
| -- GPDB_12_MERGE_FIXME: this function extract the number such as [5,10] out of |
| -- the string "Partition selected: 5 out of 10". We have temporarily broken |
| -- that when we reimplemented dynamic seq scan. Currently only the number of |
| -- selected partitions is avalable, get the total number of partitions back |
| -- post merge. |
| create or replace function get_selected_parts(explain_query text) returns text as |
| $$ |
| import re |
| rv = plpy.execute(explain_query) |
| search_text = 'Dynamic Seq Scan on ' |
| result = [] |
| result.append(0) |
| result.append(0) |
| selected = 0 |
| out_of = 0 |
| pattern = re.compile(r"\s+Number of partitions to scan: (?P<selected>\d+)") |
| for i in range(len(rv)): |
| cur_line = rv[i]['QUERY PLAN'] |
| if search_text.lower() in cur_line.lower(): |
| j = i+1 |
| temp_line = rv[j]['QUERY PLAN'] |
| while (not pattern.match(temp_line)): |
| j += 1 |
| if j == len(rv) - 1: |
| break |
| temp_line = rv[j]['QUERY PLAN'] |
| |
| else: |
| selected += int(pattern.match(temp_line).group('selected')) |
| result[0] = selected |
| result[1] = out_of |
| return result |
| $$ |
| language plpython3u; |
| drop table if exists partprune_foo; |
| create table partprune_foo(a int, b int, c int) partition by range (b) (start (1) end (101) every (10)); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| insert into partprune_foo select g % 5 + 1, g + 1, g % 10 + 1 from generate_series(0, 99) g; |
| analyze partprune_foo; |
| select get_selected_parts('explain select * from partprune_foo;'); |
| get_selected_parts |
| -------------------- |
| [10, 0] |
| (1 row) |
| |
| select * from partprune_foo; |
| a | b | c |
| ---+-----+---- |
| 1 | 1 | 1 |
| 3 | 3 | 3 |
| 5 | 5 | 5 |
| 1 | 6 | 6 |
| 3 | 8 | 8 |
| 5 | 10 | 10 |
| 1 | 11 | 1 |
| 3 | 13 | 3 |
| 5 | 15 | 5 |
| 1 | 16 | 6 |
| 3 | 18 | 8 |
| 5 | 20 | 10 |
| 1 | 21 | 1 |
| 3 | 23 | 3 |
| 5 | 25 | 5 |
| 1 | 26 | 6 |
| 3 | 28 | 8 |
| 5 | 30 | 10 |
| 1 | 31 | 1 |
| 3 | 33 | 3 |
| 5 | 35 | 5 |
| 1 | 36 | 6 |
| 3 | 38 | 8 |
| 5 | 40 | 10 |
| 1 | 41 | 1 |
| 3 | 43 | 3 |
| 5 | 45 | 5 |
| 1 | 46 | 6 |
| 3 | 48 | 8 |
| 5 | 50 | 10 |
| 1 | 51 | 1 |
| 3 | 53 | 3 |
| 5 | 55 | 5 |
| 1 | 56 | 6 |
| 3 | 58 | 8 |
| 5 | 60 | 10 |
| 1 | 61 | 1 |
| 3 | 63 | 3 |
| 5 | 65 | 5 |
| 1 | 66 | 6 |
| 3 | 68 | 8 |
| 5 | 70 | 10 |
| 1 | 71 | 1 |
| 3 | 73 | 3 |
| 5 | 75 | 5 |
| 1 | 76 | 6 |
| 3 | 78 | 8 |
| 5 | 80 | 10 |
| 1 | 81 | 1 |
| 3 | 83 | 3 |
| 5 | 85 | 5 |
| 1 | 86 | 6 |
| 3 | 88 | 8 |
| 5 | 90 | 10 |
| 1 | 91 | 1 |
| 3 | 93 | 3 |
| 5 | 95 | 5 |
| 1 | 96 | 6 |
| 3 | 98 | 8 |
| 5 | 100 | 10 |
| 2 | 2 | 2 |
| 4 | 4 | 4 |
| 2 | 7 | 7 |
| 4 | 9 | 9 |
| 2 | 12 | 2 |
| 4 | 14 | 4 |
| 2 | 17 | 7 |
| 4 | 19 | 9 |
| 2 | 22 | 2 |
| 4 | 24 | 4 |
| 2 | 27 | 7 |
| 4 | 29 | 9 |
| 2 | 32 | 2 |
| 4 | 34 | 4 |
| 2 | 37 | 7 |
| 4 | 39 | 9 |
| 2 | 42 | 2 |
| 4 | 44 | 4 |
| 2 | 47 | 7 |
| 4 | 49 | 9 |
| 2 | 52 | 2 |
| 4 | 54 | 4 |
| 2 | 57 | 7 |
| 4 | 59 | 9 |
| 2 | 62 | 2 |
| 4 | 64 | 4 |
| 2 | 67 | 7 |
| 4 | 69 | 9 |
| 2 | 72 | 2 |
| 4 | 74 | 4 |
| 2 | 77 | 7 |
| 4 | 79 | 9 |
| 2 | 82 | 2 |
| 4 | 84 | 4 |
| 2 | 87 | 7 |
| 4 | 89 | 9 |
| 2 | 92 | 2 |
| 4 | 94 | 4 |
| 2 | 97 | 7 |
| 4 | 99 | 9 |
| (100 rows) |
| |
| select get_selected_parts('explain select * from partprune_foo where b = 35;'); |
| get_selected_parts |
| -------------------- |
| [1, 0] |
| (1 row) |
| |
| select * from partprune_foo where b = 35; |
| a | b | c |
| ---+----+--- |
| 5 | 35 | 5 |
| (1 row) |
| |
| select get_selected_parts('explain select * from partprune_foo where b < 35;'); |
| get_selected_parts |
| -------------------- |
| [4, 0] |
| (1 row) |
| |
| select * from partprune_foo where b < 35; |
| a | b | c |
| ---+----+---- |
| 2 | 2 | 2 |
| 4 | 4 | 4 |
| 2 | 7 | 7 |
| 4 | 9 | 9 |
| 2 | 12 | 2 |
| 4 | 14 | 4 |
| 2 | 17 | 7 |
| 4 | 19 | 9 |
| 2 | 22 | 2 |
| 4 | 24 | 4 |
| 2 | 27 | 7 |
| 4 | 29 | 9 |
| 2 | 32 | 2 |
| 4 | 34 | 4 |
| 1 | 1 | 1 |
| 3 | 3 | 3 |
| 5 | 5 | 5 |
| 1 | 6 | 6 |
| 3 | 8 | 8 |
| 5 | 10 | 10 |
| 1 | 11 | 1 |
| 3 | 13 | 3 |
| 5 | 15 | 5 |
| 1 | 16 | 6 |
| 3 | 18 | 8 |
| 5 | 20 | 10 |
| 1 | 21 | 1 |
| 3 | 23 | 3 |
| 5 | 25 | 5 |
| 1 | 26 | 6 |
| 3 | 28 | 8 |
| 5 | 30 | 10 |
| 1 | 31 | 1 |
| 3 | 33 | 3 |
| (34 rows) |
| |
| select get_selected_parts('explain select * from partprune_foo where b in (5, 6, 14, 23);'); |
| get_selected_parts |
| -------------------- |
| [3, 0] |
| (1 row) |
| |
| select * from partprune_foo where b in (5, 6, 14, 23); |
| a | b | c |
| ---+----+--- |
| 5 | 5 | 5 |
| 1 | 6 | 6 |
| 3 | 23 | 3 |
| 4 | 14 | 4 |
| (4 rows) |
| |
| select get_selected_parts('explain select * from partprune_foo where b < 15 or b > 60;'); |
| get_selected_parts |
| -------------------- |
| [7, 0] |
| (1 row) |
| |
| select * from partprune_foo where b < 15 or b > 60; |
| a | b | c |
| ---+-----+---- |
| 2 | 2 | 2 |
| 4 | 4 | 4 |
| 2 | 7 | 7 |
| 4 | 9 | 9 |
| 2 | 12 | 2 |
| 4 | 14 | 4 |
| 2 | 62 | 2 |
| 4 | 64 | 4 |
| 2 | 67 | 7 |
| 4 | 69 | 9 |
| 2 | 72 | 2 |
| 4 | 74 | 4 |
| 2 | 77 | 7 |
| 4 | 79 | 9 |
| 2 | 82 | 2 |
| 4 | 84 | 4 |
| 2 | 87 | 7 |
| 4 | 89 | 9 |
| 2 | 92 | 2 |
| 4 | 94 | 4 |
| 2 | 97 | 7 |
| 4 | 99 | 9 |
| 1 | 1 | 1 |
| 3 | 3 | 3 |
| 5 | 5 | 5 |
| 1 | 6 | 6 |
| 3 | 8 | 8 |
| 5 | 10 | 10 |
| 1 | 11 | 1 |
| 3 | 13 | 3 |
| 1 | 61 | 1 |
| 3 | 63 | 3 |
| 5 | 65 | 5 |
| 1 | 66 | 6 |
| 3 | 68 | 8 |
| 5 | 70 | 10 |
| 1 | 71 | 1 |
| 3 | 73 | 3 |
| 5 | 75 | 5 |
| 1 | 76 | 6 |
| 3 | 78 | 8 |
| 5 | 80 | 10 |
| 1 | 81 | 1 |
| 3 | 83 | 3 |
| 5 | 85 | 5 |
| 1 | 86 | 6 |
| 3 | 88 | 8 |
| 5 | 90 | 10 |
| 1 | 91 | 1 |
| 3 | 93 | 3 |
| 5 | 95 | 5 |
| 1 | 96 | 6 |
| 3 | 98 | 8 |
| 5 | 100 | 10 |
| (54 rows) |
| |
| select get_selected_parts('explain select * from partprune_foo where b = 150;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| select * from partprune_foo where b = 150; |
| a | b | c |
| ---+---+--- |
| (0 rows) |
| |
| select get_selected_parts('explain select * from partprune_foo where b = a*5;'); |
| get_selected_parts |
| -------------------- |
| [10, 0] |
| (1 row) |
| |
| select * from partprune_foo where b = a*5; |
| a | b | c |
| ---+----+--- |
| 5 | 25 | 5 |
| (1 row) |
| |
| -- Test with IN() lists |
| -- Number of elements > threshold, partition elimination is not performed |
| set optimizer_array_expansion_threshold = 3; |
| select get_selected_parts('explain select * from partprune_foo where b in (5, 6, 14, 23);'); |
| get_selected_parts |
| -------------------- |
| [3, 0] |
| (1 row) |
| |
| select * from partprune_foo where b in (5, 6, 14, 23); |
| a | b | c |
| ---+----+--- |
| 3 | 23 | 3 |
| 5 | 5 | 5 |
| 4 | 14 | 4 |
| 1 | 6 | 6 |
| (4 rows) |
| |
| reset optimizer_array_expansion_threshold; |
| -- Test "ANY (<array>)" syntax. |
| select get_selected_parts($$ explain select * from partprune_foo where b = ANY ('{5, 6, 14}') $$); |
| get_selected_parts |
| -------------------- |
| [2, 0] |
| (1 row) |
| |
| select * from partprune_foo where b = ANY ('{5, 6, 14}'); |
| a | b | c |
| ---+----+--- |
| 1 | 6 | 6 |
| 5 | 5 | 5 |
| 4 | 14 | 4 |
| (3 rows) |
| |
| select get_selected_parts($$ explain select * from partprune_foo where b < ANY ('{12, 14, 11}') $$); |
| get_selected_parts |
| -------------------- |
| [2, 0] |
| (1 row) |
| |
| select * from partprune_foo where b < ANY ('{12, 14, 11}'); |
| a | b | c |
| ---+----+---- |
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 1 | 6 | 6 |
| 2 | 7 | 7 |
| 1 | 11 | 1 |
| 2 | 12 | 2 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
| 5 | 5 | 5 |
| 3 | 8 | 8 |
| 4 | 9 | 9 |
| 5 | 10 | 10 |
| 3 | 13 | 3 |
| (13 rows) |
| |
| -- Check for all the different number of partition selections |
| DROP TABLE IF EXISTS DATE_PARTS; |
| NOTICE: table "date_parts" does not exist, skipping |
| CREATE TABLE DATE_PARTS (id int, year int, month int, day int, region text) |
| DISTRIBUTED BY (id) |
| PARTITION BY RANGE (year) |
| SUBPARTITION BY LIST (month) |
| SUBPARTITION TEMPLATE ( |
| SUBPARTITION Q1 VALUES (1, 2, 3), |
| SUBPARTITION Q2 VALUES (4 ,5 ,6), |
| SUBPARTITION Q3 VALUES (7, 8, 9), |
| SUBPARTITION Q4 VALUES (10, 11, 12), |
| DEFAULT SUBPARTITION other_months ) |
| SUBPARTITION BY RANGE(day) |
| SUBPARTITION TEMPLATE ( |
| START (1) END (31) EVERY (10), |
| DEFAULT SUBPARTITION other_days) |
| ( START (2002) END (2012) EVERY (4), |
| DEFAULT PARTITION outlying_years ); |
| insert into DATE_PARTS select i, extract(year from dt), extract(month from dt), extract(day from dt), NULL from (select i, '2002-01-01'::date + i * interval '1 day' day as dt from generate_series(1, 3650) as i) as t; |
| -- Expected total parts => 4 * 1 * 4 => 16: |
| -- TODO #141973839: we selected extra parts because of disjunction: 32 parts: 4 * 2 * 4 |
| select get_selected_parts('explain analyze select * from DATE_PARTS where month between 1 and 3;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- Expected total parts => 4 * 2 * 4 => 32: |
| -- TODO #141973839: we selected extra parts because of disjunction: 48 parts: 4 * 3 * 4 |
| select get_selected_parts('explain analyze select * from DATE_PARTS where month between 1 and 4;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- Expected total parts => 1 * 2 * 4 => 8: |
| -- TODO #141973839: we selected extra parts because of disjunction: 24 parts: 2 * 3 * 4 |
| select get_selected_parts('explain analyze select * from DATE_PARTS where year = 2003 and month between 1 and 4;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- 1 :: 5 :: 4 => 20 // Only default for year |
| select get_selected_parts('explain analyze select * from DATE_PARTS where year = 1999;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- 4 :: 1 :: 4 => 16 // Only default for month |
| select get_selected_parts('explain analyze select * from DATE_PARTS where month = 13;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- 1 :: 1 :: 4 => 4 // Default for both year and month |
| select get_selected_parts('explain analyze select * from DATE_PARTS where year = 1999 and month = 13;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- 4 :: 5 :: 1 => 20 // Only default part for day |
| select get_selected_parts('explain analyze select * from DATE_PARTS where day = 40;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- General predicate |
| -- TODO #141973839. We expected 112 parts: (month = 1) => 4 * 1 * 4 => 16, month > 3 => 4 * 4 * 4 => 64, month in (0, 1, 2) => 4 * 1 * 4 => 16, month is NULL => 4 * 1 * 4 => 16. |
| -- However, we selected 128 parts: (month = 1) => 4 * 1 * 4 => 16, month > 3 => 4 * 4 * 4 => 64, month in (0, 1, 2) => 4 * 2 * 4 => 32, month is NULL => 4 * 1 * 4 => 16. |
| select get_selected_parts('explain analyze select * from DATE_PARTS where month = 1 union all select * from DATE_PARTS where month > 3 union all select * from DATE_PARTS where month in (0,1,2) union all select * from DATE_PARTS where month is null;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- Equality predicate |
| -- 16 partitions => 4 from year x 1 from month x 4 from days. |
| select get_selected_parts('explain analyze select * from DATE_PARTS where month = 3;'); -- Not working (it only produces general) |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- More Equality and General Predicates --- |
| create table foo(a int, b int) |
| partition by list (b) |
| (partition p1 values(1,3), partition p2 values(4,2), default partition other); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| -- General predicate |
| -- Total 6 parts. b = 1: 1 part, b > 3: 2 parts, b in (0, 1): 2 parts. b is null: 1 part |
| select get_selected_parts('explain analyze select * from foo where b = 1 union all select * from foo where b > 3 union all select * from foo where b in (0,1) union all select * from foo where b is null;'); |
| get_selected_parts |
| -------------------- |
| [6, 0] |
| (1 row) |
| |
| drop table if exists pt; |
| NOTICE: table "pt" does not exist, skipping |
| CREATE TABLE pt (id int, gender varchar(2)) |
| DISTRIBUTED BY (id) |
| PARTITION BY LIST (gender) |
| ( PARTITION girls VALUES ('F', NULL), |
| PARTITION boys VALUES ('M'), |
| DEFAULT PARTITION other ); |
| -- General filter |
| -- TODO #141916623. Expecting 6 parts, but optimizer plan selects 7 parts. The 6 parts breakdown is: gender = 'F': 1 part, gender < 'M': 2 parts (including default), gender in ('F', F'M'): 2 parts, gender is null => 1 part |
| select get_selected_parts('explain analyze select * from pt where gender = ''F'' union all select * from pt where gender < ''M'' union all select * from pt where gender in (''F'', ''FM'') union all select * from pt where gender is null;'); |
| get_selected_parts |
| -------------------- |
| [6, 0] |
| (1 row) |
| |
| -- DML |
| -- Non-default part |
| insert into DATE_PARTS values (-1, 2004, 11, 30, NULL); |
| select * from date_parts_1_prt_2_2_prt_q4_3_prt_4 where id < 0; |
| id | year | month | day | region |
| ----+------+-------+-----+-------- |
| -1 | 2004 | 11 | 30 | |
| (1 row) |
| |
| -- Default year |
| insert into DATE_PARTS values (-2, 1999, 11, 30, NULL); |
| select * from date_parts_1_prt_outlying_years_2_prt_q4_3_prt_4 where id < 0; |
| id | year | month | day | region |
| ----+------+-------+-----+-------- |
| -2 | 1999 | 11 | 30 | |
| (1 row) |
| |
| -- Default month |
| insert into DATE_PARTS values (-3, 2004, 20, 30, NULL); |
| select * from date_parts_1_prt_2_2_prt_other_months where id < 0; |
| id | year | month | day | region |
| ----+------+-------+-----+-------- |
| -3 | 2004 | 20 | 30 | |
| (1 row) |
| |
| -- Default day |
| insert into DATE_PARTS values (-4, 2004, 10, 50, NULL); |
| select * from date_parts_1_prt_2_2_prt_q4_3_prt_other_days where id < 0; |
| id | year | month | day | region |
| ----+------+-------+-----+-------- |
| -4 | 2004 | 10 | 50 | |
| (1 row) |
| |
| -- Default everything |
| insert into DATE_PARTS values (-5, 1999, 20, 50, NULL); |
| select * from date_parts_1_prt_outlying_years_2_prt_other_mo_3_prt_other_days where id < 0; |
| id | year | month | day | region |
| ----+------+-------+-----+-------- |
| -5 | 1999 | 20 | 50 | |
| (1 row) |
| |
| -- Default month + day but not year |
| insert into DATE_PARTS values (-6, 2002, 20, 50, NULL); |
| select * from date_parts_1_prt_2_2_prt_other_months_3_prt_other_days where id < 0; |
| id | year | month | day | region |
| ----+------+-------+-----+-------- |
| -6 | 2002 | 20 | 50 | |
| (1 row) |
| |
| -- Dropped columns with exchange |
| drop table if exists sales; |
| NOTICE: table "sales" does not exist, skipping |
| CREATE TABLE sales (trans_id int, to_be_dropped1 int, date date, amount |
| decimal(9,2), to_be_dropped2 int, region text) |
| DISTRIBUTED BY (trans_id) |
| PARTITION BY RANGE (date) |
| SUBPARTITION BY LIST (region) |
| SUBPARTITION TEMPLATE |
| ( SUBPARTITION usa VALUES ('usa'), |
| SUBPARTITION asia VALUES ('asia'), |
| SUBPARTITION europe VALUES ('europe'), |
| DEFAULT SUBPARTITION other_regions) |
| (START (date '2011-01-01') INCLUSIVE |
| END (date '2012-01-01') EXCLUSIVE |
| EVERY (INTERVAL '3 month'), |
| DEFAULT PARTITION outlying_dates ); |
| -- This will introduce different column numbers in subsequent part tables |
| alter table sales drop column to_be_dropped1; |
| alter table sales drop column to_be_dropped2; |
| -- Create the exchange candidate without dropped columns |
| drop table if exists sales_exchange_part; |
| NOTICE: table "sales_exchange_part" does not exist, skipping |
| create table sales_exchange_part (trans_id int, date date, amount |
| decimal(9,2), region text); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'trans_id' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| -- Insert some data |
| insert into sales_exchange_part values(1, '2011-01-01', 10.1, 'usa'); |
| -- Exchange |
| ALTER TABLE sales |
| ALTER PARTITION FOR (date '2011-01-01') |
| EXCHANGE PARTITION FOR ('usa') WITH TABLE sales_exchange_part ; |
| ANALYZE sales; |
| -- TODO: #141973839. Expected 10 parts, currently selecting 15 parts. First level: 4 parts + 1 default. Second level 2 parts. Total 10 parts. |
| select get_selected_parts('explain analyze select * from sales where region = ''usa'' or region = ''asia'';'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| select * from sales where region = 'usa' or region = 'asia'; |
| trans_id | date | amount | region |
| ----------+------------+--------+-------- |
| 1 | 01-01-2011 | 10.10 | usa |
| (1 row) |
| |
| -- Test DynamicIndexScan with extra filter |
| create index idx_sales_date on sales(date); |
| explain select * from sales where date = '2011-01-01' and region = 'usa'; |
| QUERY PLAN |
| ----------------------------------------------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.12..8.16 rows=1 width=19) |
| -> Index Scan using sales_1_prt_2_2_prt_usa_date_idx on sales_1_prt_2_2_prt_usa sales (cost=0.12..8.14 rows=1 width=19) |
| Index Cond: (date = '01-01-2011'::date) |
| Filter: (region = 'usa'::text) |
| Optimizer: Postgres query optimizer |
| (5 rows) |
| |
| select * from sales where date = '2011-01-01' and region = 'usa'; |
| trans_id | date | amount | region |
| ----------+------------+--------+-------- |
| 1 | 01-01-2011 | 10.10 | usa |
| (1 row) |
| |
| -- Updating partition key |
| select * from sales_1_prt_2_2_prt_usa; |
| trans_id | date | amount | region |
| ----------+------------+--------+-------- |
| 1 | 01-01-2011 | 10.10 | usa |
| (1 row) |
| |
| select * from sales_1_prt_2_2_prt_europe; |
| trans_id | date | amount | region |
| ----------+------+--------+-------- |
| (0 rows) |
| |
| update sales set region = 'europe' where trans_id = 1; |
| select * from sales_1_prt_2_2_prt_europe; |
| trans_id | date | amount | region |
| ----------+------------+--------+-------- |
| 1 | 01-01-2011 | 10.10 | europe |
| (1 row) |
| |
| select * from sales_1_prt_2_2_prt_usa; |
| trans_id | date | amount | region |
| ----------+------+--------+-------- |
| (0 rows) |
| |
| select * from sales; |
| trans_id | date | amount | region |
| ----------+------------+--------+-------- |
| 1 | 01-01-2011 | 10.10 | europe |
| (1 row) |
| |
| -- Distinct From |
| drop table if exists bar; |
| NOTICE: table "bar" does not exist, skipping |
| CREATE TABLE bar (i INTEGER, j decimal) |
| partition by list (j) |
| subpartition by range (i) subpartition template (start(1) end(4) every(2)) |
| (partition p1 values(0.2,2.8, NULL), partition p2 values(1.7,3.1), |
| partition p3 values(5.6), default partition other); |
| NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Apache Cloudberry data distribution key for this table. |
| HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. |
| insert into bar values(1, 0.2); --p1 |
| insert into bar values(1, 1.7); --p2 |
| insert into bar values(1, 2.1); --default |
| insert into bar values(1, 5.6); --default |
| insert into bar values(1, NULL); --p1 |
| -- In-equality |
| -- 8 parts: All 4 parts on first level and each will have 2 range parts |
| select get_selected_parts('explain analyze select * from bar where j>0.02;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- 6 parts: Excluding 1 list parts at first level. So, 3 at first level and each has 2 at second level. |
| select get_selected_parts('explain analyze select * from bar where j>2.8;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- Distinct From |
| -- 6 parts: Everything except 1 part that contains 5.6. |
| select get_selected_parts('explain analyze select * from bar where j is distinct from 5.6;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- 8 parts: NULL is shared with others on p1. So, all 8 parts. |
| select get_selected_parts('explain analyze select * from bar where j is distinct from NULL;'); |
| get_selected_parts |
| -------------------- |
| [0, 0] |
| (1 row) |
| |
| -- Table partitioned by boolean column |
| CREATE TABLE pt_bool_tab |
| ( |
| col1 int, |
| col2 bool |
| ) |
| distributed by (col1) |
| partition by list(col2) |
| ( |
| partition part1 values(true), |
| partition part2 values(false) |
| ); |
| INSERT INTO pt_bool_tab SELECT i, true FROM generate_series(1,3)i; |
| INSERT INTO pt_bool_tab SELECT i, false FROM generate_series(1,2)i; |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: (col2 IS TRUE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS true; |
| col1 | col2 |
| ------+------ |
| 1 | t |
| 2 | t |
| 3 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: (col2 IS FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS false; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS NULL; |
| QUERY PLAN |
| ------------------------------------------ |
| Result (cost=0.00..0.00 rows=0 width=5) |
| One-Time Filter: false |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (3 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS NULL; |
| col1 | col2 |
| ------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS unknown; |
| QUERY PLAN |
| ------------------------------------------ |
| Result (cost=0.00..0.00 rows=0 width=5) |
| One-Time Filter: false |
| Optimizer: GPORCA |
| (3 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS unknown; |
| col1 | col2 |
| ------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS NOT true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: (col2 IS NOT TRUE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS NOT true; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS NOT false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: (col2 IS NOT FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS NOT false; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS NOT unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: (col2 IS NOT UNKNOWN) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS NOT unknown; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | t |
| 2 | f |
| 2 | t |
| 3 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE col2 IS NOT NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: (NOT (col2 IS NULL)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE col2 IS NOT NULL; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | t |
| 2 | f |
| 2 | t |
| 3 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: ((NOT col2) IS TRUE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS true; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: ((NOT col2) IS FALSE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS false; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: ((NOT col2) IS NULL) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS NULL; |
| col1 | col2 |
| ------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: ((NOT col2) IS UNKNOWN) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS unknown; |
| col1 | col2 |
| ------+------ |
| (0 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: ((NOT col2) IS NOT TRUE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT true; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 2) |
| Filter: ((NOT col2) IS NOT FALSE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT false; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: ((NOT col2) IS NOT UNKNOWN) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT unknown; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | t |
| 2 | f |
| 2 | t |
| 3 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 2) |
| Filter: (NOT ((NOT col2) IS NULL)) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab WHERE (not col2) IS NOT NULL; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | t |
| 2 | f |
| 2 | t |
| 3 | t |
| (5 rows) |
| |
| CREATE TABLE pt_bool_tab_df |
| ( |
| col1 int, |
| col2 bool |
| ) |
| distributed by (col1) |
| partition by list(col2) |
| ( |
| partition part1 values(true), |
| partition part2 values(false), |
| default partition def |
| ); |
| INSERT INTO pt_bool_tab_df SELECT i, true FROM generate_series(1,3)i; |
| INSERT INTO pt_bool_tab_df SELECT i, false FROM generate_series(1,2)i; |
| INSERT INTO pt_bool_tab_df SELECT i, NULL FROM generate_series(1,1)i; |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS TRUE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS true; |
| col1 | col2 |
| ------+------ |
| 1 | t |
| 2 | t |
| 3 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS false; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS NULL) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS NULL; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS UNKNOWN) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS unknown; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (col2 IS NOT TRUE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT true; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| 1 | |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (col2 IS NOT FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT false; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| 1 | |
| (4 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (col2 IS NOT UNKNOWN) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT unknown; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 2 | t |
| 3 | t |
| 1 | f |
| 1 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (NOT (col2 IS NULL)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE col2 IS NOT NULL; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 2 | t |
| 3 | t |
| 1 | f |
| 1 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: ((NOT col2) IS TRUE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS true; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: ((NOT col2) IS FALSE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS false; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: ((NOT col2) IS NULL) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NULL; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: ((NOT col2) IS UNKNOWN) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS unknown; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT true; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: ((NOT col2) IS NOT TRUE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT true; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| 1 | |
| (4 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT false; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: ((NOT col2) IS NOT FALSE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT false; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 1 | f |
| 1 | |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT unknown; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: ((NOT col2) IS NOT UNKNOWN) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT unknown; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 2 | t |
| 3 | t |
| 1 | f |
| 1 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT NULL; |
| QUERY PLAN |
| ------------------------------------------------------------------------------ |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_df (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: (NOT ((NOT col2) IS NULL)) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_df WHERE (not col2) IS NOT NULL; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 2 | t |
| 3 | t |
| 1 | f |
| 1 | t |
| (5 rows) |
| |
| CREATE TABLE pt_bool_tab_null |
| ( |
| col1 int, |
| col2 bool |
| ) |
| distributed by (col1) |
| partition by list(col2) |
| ( |
| partition part1 values(true), |
| partition part2 values(false), |
| partition part3 values(null) |
| ); |
| INSERT INTO pt_bool_tab_null SELECT i, true FROM generate_series(1,3)i; |
| INSERT INTO pt_bool_tab_null SELECT i, false FROM generate_series(1,2)i; |
| INSERT INTO pt_bool_tab_null SELECT i, NULL FROM generate_series(1,1)i; |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS true; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS TRUE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS true; |
| col1 | col2 |
| ------+------ |
| 1 | t |
| 2 | t |
| 3 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS false; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS false; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 2 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS NULL; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS NULL) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS NULL; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS unknown; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: (col2 IS UNKNOWN) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS unknown; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT true; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (col2 IS NOT TRUE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT true; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 2 | f |
| 1 | |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT false; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (col2 IS NOT FALSE) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT false; |
| col1 | col2 |
| ------+------ |
| 2 | t |
| 3 | t |
| 1 | t |
| 1 | |
| (4 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT unknown; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (col2 IS NOT UNKNOWN) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT unknown; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 2 | t |
| 3 | t |
| 1 | f |
| 1 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT NULL; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: (NOT (col2 IS NULL)) |
| Optimizer: Pivotal Optimizer (GPORCA) |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE col2 IS NOT NULL; |
| col1 | col2 |
| ------+------ |
| 2 | f |
| 2 | t |
| 3 | t |
| 1 | f |
| 1 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS true; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: ((NOT col2) IS TRUE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS true; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 2 | f |
| (2 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS false; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 1 (out of 3) |
| Filter: ((NOT col2) IS FALSE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS false; |
| col1 | col2 |
| ------+------ |
| 1 | t |
| 2 | t |
| 3 | t |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NULL; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: ((NOT col2) IS NULL) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NULL; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS unknown; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: ((NOT col2) IS UNKNOWN) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS unknown; |
| col1 | col2 |
| ------+------ |
| 1 | |
| (1 row) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT true; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: ((NOT col2) IS NOT TRUE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT true; |
| col1 | col2 |
| ------+------ |
| 1 | t |
| 1 | |
| 2 | t |
| 3 | t |
| (4 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT false; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 2 (out of 3) |
| Filter: ((NOT col2) IS NOT FALSE) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT false; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | |
| 2 | f |
| (3 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT unknown; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: ((NOT col2) IS NOT UNKNOWN) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT unknown; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | t |
| 2 | f |
| 2 | t |
| 3 | t |
| (5 rows) |
| |
| EXPLAIN SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT NULL; |
| QUERY PLAN |
| -------------------------------------------------------------------------------- |
| Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=5) |
| -> Dynamic Seq Scan on pt_bool_tab_null (cost=0.00..431.00 rows=1 width=5) |
| Number of partitions to scan: 3 (out of 3) |
| Filter: (NOT ((NOT col2) IS NULL)) |
| Optimizer: GPORCA |
| (5 rows) |
| |
| SELECT * FROM pt_bool_tab_null WHERE (not col2) IS NOT NULL; |
| col1 | col2 |
| ------+------ |
| 1 | f |
| 1 | t |
| 2 | f |
| 2 | t |
| 3 | t |
| (5 rows) |
| |
| RESET ALL; |