blob: 474bd75b40645cdceee779d5e604199766179b7a [file] [log] [blame]
--
-- Test Cases to check Index scan, Index Only scan,
-- Dynamic Index scan & Dynamic Index only scan costing
--
---------------------------------------------------------------------
-- Scenario1: Verify impact of unused index column in predicate,
-- which helps in selecting best index in a multiple index scenario.
---------------------------------------------------------------------
-- Case A : Index - idx_ab, Columns used in predicate : a
-- Case B : Index - idx_ab, Columns used in predicate : b
-- In the above two cases, the index scan using idx_ab should be higher
-- in CASE B, compared for CASE A, as the in Case-B, index column
-- of higher significance is unused i.e. col 'a'
drop table if exists foo;
NOTICE: table "foo" does not exist, skipping
create table foo (a int , b int, c int) distributed by (a);
insert into foo select i,i,i from generate_series(1,5)i;
-- Adding 1,1,1 in the table so that we have different values for NDV and table rows.
insert into foo select 1,1,1*i/i from generate_series(1,5)i;
-- 1.1 Test case for index scans
CREATE INDEX idx_foo_ab ON foo USING btree(a,b);
CREATE INDEX idx_foo_ba ON foo USING btree(b,a);
analyze foo;
-- index idx_foo_ab should be selected
explain select * from foo where a=1;
QUERY PLAN
-----------------------------------------------------------------------------
Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=6 width=12)
-> Index Scan using idx_foo_ab on foo (cost=0.00..6.00 rows=2 width=12)
Index Cond: (a = 1)
Optimizer: GPORCA
(4 rows)
-- Index idx_foo_ba should be selected
explain select * from foo where b=1;
QUERY PLAN
-----------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=6 width=12)
-> Index Scan using idx_foo_ba on foo (cost=0.00..6.00 rows=2 width=12)
Index Cond: (b = 1)
Optimizer: GPORCA
(4 rows)
drop index idx_foo_ab;
drop index idx_foo_ba;
-- 1.2 Test case for index only scans
CREATE INDEX idx_foo_abc ON foo USING btree(a,b,c);
CREATE INDEX idx_foo_cba ON foo USING btree(c,b,a);
vacuum analyze foo;
-- Index idx_foo_abc should be selected
explain select * from foo where a=1;
QUERY PLAN
-----------------------------------------------------------------------------------
Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=6 width=12)
-> Index Only Scan using idx_foo_abc on foo (cost=0.00..6.00 rows=2 width=12)
Index Cond: (a = 1)
Optimizer: GPORCA
(4 rows)
-- Index idx_foo_cba should be selected
explain select * from foo where c=1;
QUERY PLAN
-----------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..6.00 rows=6 width=12)
-> Index Only Scan using idx_foo_cba on foo (cost=0.00..6.00 rows=2 width=12)
Index Cond: (c = 1)
Optimizer: GPORCA
(4 rows)
drop index idx_foo_abc;
drop index idx_foo_cba;
-- 1.3 Test case for dynamic index scans
drop table if exists foo;
drop table if exists bar_PT;
NOTICE: table "bar_pt" does not exist, skipping
create table foo (a int , b int, c int) distributed by (a);
insert into foo select i,i,i from generate_series(1,5)i;
analyze foo;
-- Partitioned Table
create table bar_PT (a int, b int, c int) partition by range(a) (start (1) inclusive end (12) every (2)) distributed by (a);
insert into bar_PT select i,i,i from generate_series(1,11)i;
CREATE INDEX idx_bar_PT_ab ON bar_PT USING btree(a,b);
CREATE INDEX idx_bar_PT_ba ON bar_PT USING btree(b,a);
analyze bar_PT;
-- Index idx_bar_PT_ab should be selected
explain select * from bar_PT join foo on bar_PT.a =foo.a;
QUERY PLAN
-----------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..461.00 rows=5 width=24)
-> Nested Loop (cost=0.00..461.00 rows=2 width=24)
Join Filter: true
-> Seq Scan on foo (cost=0.00..431.00 rows=2 width=12)
-> Dynamic Index Scan on idx_bar_pt_ab on bar_pt (cost=0.00..30.00 rows=1 width=12)
Index Cond: (a = foo.a)
Number of partitions to scan: 6 (out of 6)
Optimizer: GPORCA
(8 rows)
-- Index idx_bar_PT_ba should be selected
explain select * from bar_PT join foo on bar_PT.b =foo.b;
QUERY PLAN
-----------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..461.00 rows=5 width=24)
-> Nested Loop (cost=0.00..461.00 rows=2 width=24)
Join Filter: true
-> Broadcast Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=5 width=12)
-> Seq Scan on foo (cost=0.00..431.00 rows=2 width=12)
-> Dynamic Index Scan on idx_bar_pt_ba on bar_pt (cost=0.00..30.00 rows=1 width=12)
Index Cond: (b = foo.b)
Number of partitions to scan: 6 (out of 6)
Optimizer: GPORCA
(9 rows)
drop index idx_bar_PT_ab;
drop index idx_bar_PT_ba;
-- 1.4 Test case for dynamic index only scans
CREATE INDEX idx_bar_PT_abc ON bar_PT USING btree(a,b,c);
CREATE INDEX idx_bar_PT_cba ON bar_PT USING btree(c,b,a);
vacuum analyze bar_PT;
-- Index idx_bar_PT_abc should be selected
explain select * from bar_PT join foo on bar_PT.a =foo.a;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..461.00 rows=5 width=24)
-> Nested Loop (cost=0.00..461.00 rows=2 width=24)
Join Filter: true
-> Seq Scan on foo (cost=0.00..431.00 rows=2 width=12)
-> Dynamic Index Only Scan on idx_bar_pt_abc on bar_pt (cost=0.00..30.00 rows=1 width=12)
Index Cond: (a = foo.a)
Number of partitions to scan: 6 (out of 6)
Optimizer: GPORCA
(8 rows)
-- Index idx_bar_PT_cba should be selected
explain select * from bar_PT join foo on bar_PT.c =foo.c;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..461.00 rows=5 width=24)
-> Nested Loop (cost=0.00..461.00 rows=2 width=24)
Join Filter: true
-> Broadcast Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=5 width=12)
-> Seq Scan on foo (cost=0.00..431.00 rows=2 width=12)
-> Dynamic Index Only Scan on idx_bar_pt_cba on bar_pt (cost=0.00..30.00 rows=1 width=12)
Index Cond: (c = foo.c)
Number of partitions to scan: 6 (out of 6)
Optimizer: GPORCA
(9 rows)
drop table if exists foo;
drop table if exists bar_PT;
------------------------------------------------
-- Scenario2: Unindexed predicate column in index.
------------------------------------------------
-- If the index does not cover all the columns of the predicate, than a scan cost
-- using it should be higher compared to an index which covers all the predicate columns.
drop table if exists foo;
NOTICE: table "foo" does not exist, skipping
create table foo (a int , b int, c int) distributed by (a);
insert into foo select i,i,i from generate_series(1,5)i;
-- Adding 1,1,1 in the table so that we have different values for NDV and table rows.
insert into foo select 1,1,1*i/i from generate_series(1,5)i;
-- 2.1 Test case for index scans
CREATE INDEX idx_foo_a ON foo USING btree(a);
CREATE INDEX idx_foo_abc ON foo USING btree(a,b,c);
vacuum analyze foo;
-- Query1 - Index idx_foo_a should be selected.
explain select * from foo where a=1;
QUERY PLAN
-----------------------------------------------------------------------------
Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=6 width=12)
-> Index Scan using idx_foo_a on foo (cost=0.00..6.00 rows=2 width=12)
Index Cond: (a = 1)
Optimizer: GPORCA
(4 rows)
-- Query2 - Index idx_foo_abc should be selected.
explain select * from foo where a=1 and b=1 and c=1;
QUERY PLAN
-----------------------------------------------------------------------------------
Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..6.00 rows=6 width=12)
-> Index Only Scan using idx_foo_abc on foo (cost=0.00..6.00 rows=2 width=12)
Index Cond: ((a = 1) AND (b = 1) AND (c = 1))
Optimizer: GPORCA
(4 rows)
drop index idx_foo_a;
drop index idx_foo_abc;
-- 2.2 Test case for dynamic index scans
drop table if exists foo;
drop table if exists bar_PT;
NOTICE: table "bar_pt" does not exist, skipping
create table foo (a int , b int, c int) distributed by (a);
insert into foo select i,i,i from generate_series(1,5)i;
analyze foo;
-- Partitioned Table
create table bar_PT (a int, b int, c int) partition by range(a) (start (1) inclusive end (12) every (2)) distributed by (a);
insert into bar_PT select i,i,i from generate_series(1,11)i;
CREATE INDEX idx_bar_PT_a ON bar_PT USING btree(a);
CREATE INDEX idx_bar_PT_abc ON bar_PT USING btree(a,b,c);
vacuum analyze bar_PT;
-- Query1: Index idx_bar_PT_a should be selected.
explain select * from bar_PT join foo on bar_PT.a =foo.a ;
QUERY PLAN
----------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..461.00 rows=5 width=24)
-> Nested Loop (cost=0.00..461.00 rows=2 width=24)
Join Filter: true
-> Seq Scan on foo (cost=0.00..431.00 rows=2 width=12)
-> Dynamic Index Scan on idx_bar_pt_a on bar_pt (cost=0.00..30.00 rows=1 width=12)
Index Cond: (a = foo.a)
Number of partitions to scan: 6 (out of 6)
Optimizer: GPORCA
(8 rows)
-- Query2 : Index idx_bar_PT_abc should be selected.
explain select * from bar_PT join foo on bar_PT.a =foo.a and bar_PT.b =foo.b and bar_PT.c =foo.c;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..461.00 rows=5 width=24)
-> Nested Loop (cost=0.00..461.00 rows=2 width=24)
Join Filter: true
-> Seq Scan on foo (cost=0.00..431.00 rows=2 width=12)
-> Dynamic Index Only Scan on idx_bar_pt_abc on bar_pt (cost=0.00..30.00 rows=1 width=12)
Index Cond: ((a = foo.a) AND (b = foo.b) AND (c = foo.c))
Number of partitions to scan: 6 (out of 6)
Optimizer: GPORCA
(8 rows)
drop table if exists foo;
drop table if exists bar_PT;