| -- @Description Tests basic index stats after vacuuming |
| CREATE TABLE uaocs_index_stats( |
| col_int int, |
| col_text text, |
| col_numeric numeric, |
| col_unq int |
| ) with(appendonly=true, orientation=column) DISTRIBUTED RANDOMLY; |
| |
| Create index uaocs_index_stats_int_idx1 on uaocs_index_stats(col_int); |
| select * from uaocs_index_stats order by col_int; |
| |
| insert into uaocs_index_stats values(1,'aa',1001,101),(2,'bb',1002,102); |
| |
| select * from uaocs_index_stats; |
| update uaocs_index_stats set col_text=' new value' where col_int = 1; |
| select * from uaocs_index_stats; |
| vacuum uaocs_index_stats; |
| SELECT relname, reltuples FROM pg_class WHERE relname = 'uaocs_index_stats'; |
| |
| -- New strategy of VACUUM AO/CO was introduced by PR #13255 for performance enhancement. |
| -- Index dead tuples will not always be cleaned up completely after VACUUM, resulting |
| -- index stats pg_class->reltuples will not always be accurate. So ignore the stats check |
| -- for reltuples to coordinate with the new behavior. |
| -- start_ignore |
| SELECT relname, reltuples FROM pg_class WHERE relname = 'uaocs_index_stats_int_idx1'; |
| |
| -- Test to ensure that reltuples is updated for an index after lazy vacuum. |
| -- This is vital as most index AMs that depend on this tuple count (eg btree, bitmap etc) |
| -- which is passed up from the table AM during lazy vacuum. |
| -- create a fresh table for the test |
| CREATE TABLE uaocs_index_stats2( |
| col_int int, |
| col_text text, |
| col_numeric numeric, |
| col_unq int |
| ) with(appendonly=true, orientation=column) DISTRIBUTED BY (col_int); |
| |
| create index uaocs_index_stats2_int_idx1 on uaocs_index_stats2 using bitmap(col_int); |
| |
| insert into uaocs_index_stats2 values(1,'aa',1001,101),(2,'bb',1002,102); |
| |
| SELECT relname, reltuples FROM pg_class WHERE relname = 'uaocs_index_stats2_int_idx1'; |
| |
| -- first vacuum collect table stat on segments |
| vacuum uaocs_index_stats2; |
| -- inspect the state of the stats on segments |
| SELECT gp_segment_id, relname, reltuples FROM gp_dist_random('pg_class') WHERE relname = 'uaocs_index_stats2_int_idx1'; |
| -- second vacuum update index stat with table stat |
| vacuum uaocs_index_stats2; |
| -- inspect the state of the stats on segments |
| SELECT gp_segment_id, relname, reltuples FROM gp_dist_random('pg_class') WHERE relname = 'uaocs_index_stats2_int_idx1'; |
| SELECT relname, reltuples FROM pg_class WHERE relname = 'uaocs_index_stats2_int_idx1'; |
| |
| -- Test correctness of index->reltuples in consecutively VACUUM. |
| CREATE TABLE uaocs_index_stats3( |
| col_int int, |
| col_text text, |
| col_numeric numeric, |
| col_unq int |
| ) with(appendonly=true, orientation=column) DISTRIBUTED BY (col_int); |
| |
| create index uaocs_index_stats3_int_idx1 on uaocs_index_stats3(col_int); |
| |
| insert into uaocs_index_stats3 values(1,'aa',1001,101),(2,'bb',1002,102); |
| |
| select reltuples from pg_class where relname='uaocs_index_stats3'; |
| -- inspect the state of the stats on segments |
| select gp_segment_id, relname, reltuples from gp_dist_random('pg_class') where relname = 'uaocs_index_stats3_int_idx1'; |
| select reltuples from pg_class where relname='uaocs_index_stats3_int_idx1'; |
| -- 1st VACUUM, expect reltuples = 2 |
| vacuum uaocs_index_stats3; |
| select reltuples from pg_class where relname='uaocs_index_stats'; |
| -- inspect the state of the stats on segments |
| select gp_segment_id, relname, reltuples from gp_dist_random('pg_class') where relname = 'uaocs_index_stats3_int_idx1'; |
| select reltuples from pg_class where relname='uaocs_index_stats3_int_idx1'; |
| -- 2nd VACUUM, expect reltuples = 2 |
| vacuum uaocs_index_stats3; |
| select reltuples from pg_class where relname='uaocs_index_stats3'; |
| -- inspect the state of the stats on segments |
| select gp_segment_id, relname, reltuples from gp_dist_random('pg_class') where relname = 'uaocs_index_stats3_int_idx1'; |
| select reltuples from pg_class where relname='uaocs_index_stats3_int_idx1'; |
| |
| -- Prior to this fix, the case would be failed here. Given the |
| -- scenario of updating stats during VACUUM: |
| -- 1) coordinator vacuums and updates stats of its own; |
| -- 2) then coordinator dispatches vacuum to segments; |
| -- 3) coordinator combines stats received from segments to overwrite the stats of its own. |
| -- Because upstream introduced a feature which could skip full index scan uring cleanup |
| -- of B-tree indexes when possible (refer to: |
| -- https://github.com/postgres/postgres/commit/857f9c36cda520030381bd8c2af20adf0ce0e1d4), |
| -- there was a case in QD-QEs distributed deployment that some QEs could skip full index scan and |
| -- stop updating statistics, result in QD being unable to collect all QEs' stats thus overwrote |
| -- a paritial accumulated value to index->reltuples. More interesting, it usually happened starting |
| -- from the 3rd time of consecutively VACUUM after fresh inserts due to above skipping index scan |
| -- criteria. |
| -- 3rd VACUUM, expect reltuples = 2 |
| vacuum uaocs_index_stats3; |
| select reltuples from pg_class where relname='uaocs_index_stats3'; |
| -- inspect the state of the stats on segments |
| select gp_segment_id, relname, reltuples from gp_dist_random('pg_class') where relname = 'uaocs_index_stats3_int_idx1'; |
| select reltuples from pg_class where relname='uaocs_index_stats3_int_idx1'; |
| |
| drop table uaocs_index_stats; |
| drop table uaocs_index_stats2; |
| drop table uaocs_index_stats3; |