BUG #10035: PostgreSQL nodes's estimate rows bug? when alter column set statistics 0 - Mailing list pgsql-bugs
From | digoal@126.com |
---|---|
Subject | BUG #10035: PostgreSQL nodes's estimate rows bug? when alter column set statistics 0 |
Date | |
Msg-id | 20140415070242.15390.25651@wrigleys.postgresql.org Whole thread Raw |
List | pgsql-bugs |
The following bug has been logged on the website: Bug reference: 10035 Logged by: digoal.zhou Email address: digoal@126.com PostgreSQL version: 9.3.3 Operating system: CentOS 6.4 x64 Description: There is a bug in costsize.c? when i set columns statistics to zero. why planner can also compute selective in columns? TEST : Create a common table, do not close the column statistics. digoal=# create table t(id int, info text); CREATE TABLE digoal=# insert into t select 1,'test' from generate_series(1,1000000); INSERT 0 1000000 digoal=# analyze t; ANALYZE digoal=# select * from pg_stats where tablename ='t'; schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogra m_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- public | t | id | f | 0 | 4 | 1 | {1} | {1} | | 1 | | | public | t | info | f | 0 | 5 | 1 | {test} | {1} | | 1 | | | (2 rows) Create another table, close the column statistics. digoal=# create table t1(id int, info text); CREATE TABLE digoal=# alter table t1 alter column id set statistics 0; ALTER TABLE digoal=# alter table t1 alter column info set statistics 0; ALTER TABLE digoal=# insert into t1 select 1,'test' from generate_series(1,1000000); INSERT 0 1000000 digoal=# analyze t1; ANALYZE digoal=# select * from pg_stats where tablename ='t1'; schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogra m_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- (0 rows) After close the statistics, do not check in pg_stats column statistics. For the two tables to create ID column of the index. digoal=# create index idx_t_id on t(id); digoal=# create index idx_t1_id on t1(id); digoal=# select * from pg_stats where tablename ='t1'; schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | most_common_vals | most_common_freqs | histogra m_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- (0 rows) Create indexes after t1 table there is still no statistical information, this is, of course, because the PostgreSQL create indexes will not take the initiative to generate statistics. Even to generate statistics, because close the column statistics, so it is impossible to have the statistics. So in pg_class table view the corresponding data block and line, the results obtained with two tables is different also. T table data is accurate, the t1 table is not accurate. But it is also close to. digoal=# select relname,reltuples,relpages from pg_class where relname in ('t','t1'); relname | reltuples | relpages + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- t | 1e+06 | 1345 t1 | 999468 | 1345 (2 rows) Query ID is equal to 1, view the corresponding implementation plan, t1 watch the index, but evaluation of line is 4997. digoal=# explain select * from t1 where id=1; QUERY PLAN -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Index Scan using idx_t1_id on t1 (cost=0.30..1436.75 rows=4997 width=36) Index Cond: (id = 1) (2 rows) T table not go index, evaluation of line is 1000000 how difference so big? digoal=# explain select * from t where id=1; QUERY PLAN -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Seq Scan on t (cost=0.00..13845.00 rows=1000000 width=9) Filter: (id = 1) (2 rows) T1 tables should be no column statistics in theory, should evaluate no line, but it is evaluated in 4997 rows. This evaluation algorithm in costsize. C can be found, in this case is obviously not reasonable. selective estimate code at cost_index@costsize.c /* * Call index-access-method-specific code to estimate the processing cost * for scanning the index, as well as the selectivity of the index (ie, * the fraction of main-table tuples we will have to retrieve) and its * correlation to the main-table tuple order. */ OidFunctionCall7(index->amcostestimate, PointerGetDatum(root), PointerGetDatum(path), Float8GetDatum(loop_count), PointerGetDatum(&indexStartupCost), PointerGetDatum(&indexTotalCost), PointerGetDatum(&indexSelectivity), PointerGetDatum(&indexCorrelation)); /* * Save amcostestimate's results for possible use in bitmap scan planning. * We don't bother to save indexStartupCost or indexCorrelation, because a * bitmap scan doesn't care about either. */ path->indextotalcost = indexTotalCost; path->indexselectivity = indexSelectivity; /* all costs for touching index itself included here */ startup_cost += indexStartupCost; run_cost += indexTotalCost - indexStartupCost; /* estimate number of main-table tuples fetched */ tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples);
pgsql-bugs by date: