База данных и таблица ~~~~~~~~~~~~~~~~~~~~~ => create database db17; CREATE DATABASE => \c db17 You are now connected to database "db17" as user "postgres". => create table t(id serial primary key, flag boolean) => with (autovacuum_enabled = off); CREATE TABLE Вставка строк ~~~~~~~~~~~~~ => insert into t(flag) select mod(gen.id,100)=0 from generate_series(1,10000) as gen(id); INSERT 0 10000 Статистики нет: => select reltuples from pg_class where oid = 't'::regclass; reltuples ----------- 0 (1 row) => select count(*) from pg_stats where tablename = 't'; count ------- 0 (1 row) Планы запросов ~~~~~~~~~~~~~~ => explain select * from t; QUERY PLAN ------------------------------------------------------- Seq Scan on t (cost=0.00..156.15 rows=11115 width=5) (1 row) Даже без статистики оптимизатору удалось примерно угадать число строк - за счет знания размера файла и ширины полей. => explain select * from t where flag; QUERY PLAN ------------------------------------------------------ Seq Scan on t (cost=0.00..156.15 rows=5558 width=5) Filter: flag (2 rows) Селективность условия оценена как 1/2, поскольку тип предполагает 2 значения. => explain select * from t where id <= 200; QUERY PLAN ------------------------------------------------------------------------- Bitmap Heap Scan on t (cost=61.00..152.31 rows=3705 width=5) Recheck Cond: (id <= 200) -> Bitmap Index Scan on t_pkey (cost=0.00..60.07 rows=3705 width=0) Index Cond: (id <= 200) (4 rows) Здесь селективность оценена как 1/3. Это просто константа, любое другое условие неравенства будет от безысходности оценено точно так же: => explain select * from t where id <= 42; QUERY PLAN ------------------------------------------------------------------------- Bitmap Heap Scan on t (cost=61.00..152.31 rows=3705 width=5) Recheck Cond: (id <= 42) -> Bitmap Index Scan on t_pkey (cost=0.00..60.07 rows=3705 width=0) Index Cond: (id <= 42) (4 rows) Анализ таблицы ~~~~~~~~~~~~~~ => analyze t; ANALYZE => select reltuples from pg_class where oid = 't'::regclass; reltuples ----------- 10000 (1 row) => \x Expanded display is on. => select attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds, correlation from pg_stats where tablename = 't' and attname = 'id'; -[ RECORD 1 ]-----+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- attname | id null_frac | 0 n_distinct | -1 most_common_vals | most_common_freqs | histogram_bounds | {1,100,200,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,2100,2200,2300,2400,2500,2600,2700,2800,2900,3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,4000,4100,4200,4300,4400,4500,4600,4700,4800,4900,5000,5100,5200,5300,5400,5500,5600,5700,5800,5900,6000,6100,6200,6300,6400,6500,6600,6700,6800,6900,7000,7100,7200,7300,7400,7500,7600,7700,7800,7900,8000,8100,8200,8300,8400,8500,8600,8700,8800,8900,9000,9100,9200,9300,9400,9500,9600,9700,9800,9900,10000} correlation | 1 Здесь число уникальных значение представлено долей: единица означает 100%, то есть все значения уникальны вне зависимости от размера таблицы. Списка частых значений нет (все значения имеют одинаковую частоту). => select attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds, correlation from pg_stats where tablename = 't' and attname = 'flag'; -[ RECORD 1 ]-----+------------ attname | flag null_frac | 0 n_distinct | 2 most_common_vals | {f,t} most_common_freqs | {0.99,0.01} histogram_bounds | correlation | 0.980496 Здесь наоборот, есть список частых значений. Поскольку их всего два, в гистограмме нет смысла. => \x Expanded display is off. Планы запросов ~~~~~~~~~~~~~~ => explain select * from t; QUERY PLAN ------------------------------------------------------- Seq Scan on t (cost=0.00..145.00 rows=10000 width=5) (1 row) Оценка исправилась (reltuples). => explain select * from t where flag; QUERY PLAN ----------------------------------------------------- Seq Scan on t (cost=0.00..145.00 rows=100 width=5) Filter: flag (2 rows) Селективность условия оценена как 0.01 - это число из most_common_freqs для значения t. => explain select * from t where id <= 200; QUERY PLAN ------------------------------------------------------------------- Index Scan using t_pkey on t (cost=0.29..11.79 rows=200 width=5) Index Cond: (id <= 200) (2 rows) Селективность оценена исходя из гистограммы - под условие попадает ровно две корзины, отсюда 2/100, где 100 - число корзин. => \q