68.2. ÐÑимеÑÑ Ð¼Ð½Ð¾Ð³Ð¾Ð²Ð°ÑианÑной ÑÑаÑиÑÑики
68.2.1. ФÑнкÑионалÑнÑе завиÑимоÑÑи
ÐноговаÑианÑнÑÑ ÐºÐ¾ÑÑелÑÑÐ¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ пÑодемонÑÑÑиÑоваÑÑ Ð½Ð° оÑÐµÐ½Ñ Ð¿ÑоÑÑом набоÑе даннÑÑ â ÑаблиÑе Ñ Ð´Ð²ÑÐ¼Ñ ÑÑолбÑами, ÑодеÑжаÑими одинаковÑе знаÑениÑ:
CREATE TABLE t (a INT, b INT); INSERT INTO t SELECT i % 100, i % 100 FROM generate_series(1, 10000) s(i); ANALYZE t;
Ðак ÑаÑÑказÑваеÑÑÑ Ð² Разделе 14.2, планиÑовÑик Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð¿ÑеделиÑÑ Ð¼Ð¾ÑноÑÑÑ t, иÑÑ
Ð¾Ð´Ñ Ð¸Ð· ÑиÑла ÑÑÑÐ°Ð½Ð¸Ñ Ð¸ ÑÑÑок, полÑÑенного из pg_class:
SELECT relpages, reltuples FROM pg_class WHERE relname = 't';
relpages | reltuples
----------+-----------
45 | 10000РаÑпÑеделение даннÑÑ Ð¾ÑÐµÐ½Ñ Ð¿ÑоÑÑое: в каждом ÑÑолбÑе ÑодеÑжиÑÑÑ Ð²Ñего 100 ÑазлиÑнÑÑ Ð·Ð½Ð°Ñений, ÑавномеÑно ÑаÑпÑеделÑннÑÑ .
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑезÑлÑÑÐ°Ñ Ð¾ÑÐµÐ½Ð¸Ð²Ð°Ð½Ð¸Ñ ÑÑÐ»Ð¾Ð²Ð¸Ñ WHERE по ÑÑолбÑÑ a:
EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1;
QUERY PLAN
-------------------------------------------------------------------â------------
Seq Scan on t (cost=0.00..170.00 rows=100 width=8) (actual rows=100 loops=1)
Filter: (a = 1)
Rows Removed by Filter: 9900 ÐланиÑовÑик ÑаÑÑмаÑÑÐ¸Ð²Ð°ÐµÑ ÑÑловие и опÑеделÑеÑ, ÑÑо его избиÑаÑелÑноÑÑÑ Ñавна 1%. СÑÐ°Ð²Ð½Ð¸Ð²Ð°Ñ ÑÑÑ Ð¾ÑÐµÐ½ÐºÑ Ð¸ ÑакÑиÑеÑкое ÑиÑло ÑÑÑок, Ð¼Ñ Ð²Ð¸Ð´Ð¸Ð¼, ÑÑо оÑенка оÑÐµÐ½Ñ ÑоÑна (на Ñамом деле абÑолÑÑна ÑоÑна, Ñак как ÑаблиÑа оÑÐµÐ½Ñ Ð¼Ð°Ð»ÐµÐ½ÑкаÑ). ÐÑли измениÑÑ ÑÑловие WHERE, ÑÑÐ¾Ð±Ñ Ð¸ÑполÑзовалÑÑ ÑÑÐ¾Ð»Ð±ÐµÑ b, бÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑен Ñакой же план. Ðо поÑмоÑÑиÑе, ÑÑо полÑÑиÑÑÑ, еÑли Ð¼Ñ Ð¿Ñименим одинаковое ÑÑловие к двÑм ÑÑолбÑам, обÑединив иÑ
опеÑаÑоÑом AND:
EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1;
QUERY PLAN
-------------------------------------------------------------------â----------
Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=100 loops=1)
Filter: ((a = 1) AND (b = 1))
Rows Removed by Filter: 9900ÐланиÑовÑик оÑÐµÐ½Ð¸Ð²Ð°ÐµÑ Ð¸Ð·Ð±Ð¸ÑаÑелÑноÑÑÑ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð¸Ð½Ð´Ð¸Ð²Ð¸Ð´ÑалÑно, и полÑÑÐ°ÐµÑ ÑÑ Ð¶Ðµ оÑÐµÐ½ÐºÑ Ð² 1%, ÑÑо и вÑÑе. ÐаÑем он пÑедполагаеÑ, ÑÑо ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð½ÐµÐ·Ð°Ð²Ð¸ÑимÑ, Ñак ÑÑо он пеÑÐµÐ¼Ð½Ð¾Ð¶Ð°ÐµÑ Ð¸Ð·Ð±Ð¸ÑаÑелÑноÑÑи и вÑдаÑÑ Ð¾ÐºÐ¾Ð½ÑаÑелÑнÑÑ Ð¾ÑÐµÐ½ÐºÑ Ð¸Ð·Ð±Ð¸ÑаÑелÑноÑÑи, ÑавнÑÑ Ð²Ñего 0.01%. ÐÑо знаÑиÑелÑÐ½Ð°Ñ Ð½ÐµÐ´Ð¾Ð¾Ñенка, Ñак как ÑакÑиÑеÑкое ÑиÑло ÑÑÑок, ÑооÑвеÑÑÑвÑÑÑÐ¸Ñ ÑÑловиÑ, (100) на два поÑÑдка болÑÑе.
ÐÑÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ ÑеÑиÑÑ, Ñоздав обÑÐµÐºÑ ÑÑаÑиÑÑики, коÑоÑÑй ÑÐºÐ°Ð¶ÐµÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ðµ ANALYZE вÑÑиÑлиÑÑ Ð¼Ð½Ð¾Ð³Ð¾Ð²Ð°ÑианÑнÑÑ ÑÑаÑиÑÑÐ¸ÐºÑ ÑÑнкÑионалÑной завиÑимоÑÑи по двÑм ÑÑолбÑам:
CREATE STATISTICS stts (dependencies) ON a, b FROM t;
ANALYZE t;
EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1;
QUERY PLAN
-------------------------------------------------------------------â------------
Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100 loops=1)
Filter: ((a = 1) AND (b = 1))
Rows Removed by Filter: 990068.2.2. ÐноговаÑианÑное ÑиÑло ÑазлиÑнÑÑ Ð·Ð½Ð°Ñений
ÐÐ¾Ð´Ð¾Ð±Ð½Ð°Ñ Ð¿Ñоблема Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ Ñ Ð¾Ñенкой моÑноÑÑи набоÑов Ñ Ð½ÐµÑколÑкими ÑÑолбÑами, напÑимеÑ, Ñ Ð¾Ñенкой ÑиÑла гÑÑпп, коÑоÑÑе могÑÑ Ð±ÑÑÑ Ð²ÑÐ´Ð°Ð½Ñ Ð¿Ñедложением GROUP BY. Ðогда в GROUP BY Ñказан один ÑÑолбеÑ, оÑенка ÑиÑла ÑазлиÑнÑÑ
знаÑений (коÑоÑÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑвидеÑÑ ÐºÐ°Ðº ожидаемое ÑиÑло ÑÑÑок, вÑдаваемое Ñзлом HashAggregate) оÑÐµÐ½Ñ ÑоÑнаÑ:
EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a;
QUERY PLAN
-------------------------------------------------------------------â----------------------
HashAggregate (cost=195.00..196.00 rows=100 width=12) (actual rows=100 loops=1)
Group Key: a
-> Seq Scan on t (cost=0.00..145.00 rows=10000 width=4) (actual rows=10000 loops=1) Ðо оÑенка ÑиÑла гÑÑпп в запÑоÑе Ñ Ð´Ð²ÑÐ¼Ñ ÑÑолбÑами в GROUP BY без многоваÑианÑной ÑÑаÑиÑÑики, как и в пÑедÑдÑÑем пÑимеÑе, оÑлиÑаеÑÑÑ Ð¾Ñ Ð¿ÑавилÑной на поÑÑдок:
EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b;
QUERY PLAN
-------------------------------------------------------------------â-------------------------
HashAggregate (cost=220.00..230.00 rows=1000 width=16) (actual rows=100 loops=1)
Group Key: a, b
-> Seq Scan on t (cost=0.00..145.00 rows=10000 width=8) (actual rows=10000 loops=1)ÐÑли пеÑеопÑеделиÑÑ Ð¾Ð±ÑÐµÐºÑ ÑÑаÑиÑÑики, ÑÑÐ¾Ð±Ñ Ð¾Ð½ вклÑÑал подÑÑÑÑ ÑиÑла ÑазлиÑнÑÑ Ð·Ð½Ð°Ñений Ð´Ð»Ñ Ð´Ð²ÑÑ ÑÑолбÑов, оÑенка ÑÑÐ°Ð½ÐµÑ Ð³Ð¾Ñаздо лÑÑÑе:
DROP STATISTICS stts;
CREATE STATISTICS stts (dependencies, ndistinct) ON a, b FROM t;
ANALYZE t;
EXPLAIN (ANALYZE, TIMING OFF) SELECT COUNT(*) FROM t GROUP BY a, b;
QUERY PLAN
-------------------------------------------------------------------â-------------------------
HashAggregate (cost=220.00..221.00 rows=100 width=16) (actual rows=100 loops=1)
Group Key: a, b
-> Seq Scan on t (cost=0.00..145.00 rows=10000 width=8) (actual rows=10000 loops=1)68.2.3. СпиÑки MCV
Ðак ÑаÑÑказÑвалоÑÑ Ð² ÐодÑазделе 68.2.1, ÑÑаÑиÑÑика ÑÑнкÑионалÑнÑÑ Ð·Ð°Ð²Ð¸ÑимоÑÑей оÑÐµÐ½Ñ Ð½ÐµÐ´Ð¾Ñога и ÑÑÑекÑивна, но Ð¸Ð¼ÐµÐµÑ ÑеÑÑÑзное огÑаниÑение, ÑвÑзанное Ñ ÐµÑ Ð¿ÑиÑодой (оÑÑлеживаÑÑÑÑ ÑолÑко завиÑимоÑÑи на ÑÑовне ÑÑолбÑов, но не Ð¼ÐµÐ¶Ð´Ñ Ð¾ÑделÑнÑми знаÑениÑми ÑÑолбÑов).
Ð ÑÑом Ñазделе опиÑÑваÑÑÑÑ Ð¼Ð½Ð¾Ð³Ð¾Ð²Ð°ÑианÑнÑе ÑпиÑки MCV (Most-Common Values, СамÑе ÑаÑÑÑе знаÑениÑ), еÑÑеÑÑвенное ÑаÑÑиÑение ÑÑаÑиÑÑики по ÑÑолбÑам, опиÑанной в Разделе 68.1. СпиÑки MCV ÑÑÑÑанÑÑÑ ÑпомÑнÑÑое огÑаниÑение, Ñ
ÑÐ°Ð½Ñ Ð¾ÑделÑнÑе знаÑениÑ, ÑÑо, ÑазÑмееÑÑÑ, ÑÑложнÑÐµÑ Ð¿Ð¾ÑÑÑоение ÑÑаÑиÑÑики в Ñ
оде ANALYZE, а Ñакже ÑÐ½Ð¸Ð¶Ð°ÐµÑ ÑкоÑоÑÑÑ Ð¿Ð»Ð°Ð½Ð¸ÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸ ÑÑÑекÑивноÑÑÑ Ñ
ÑанениÑ.
ÐзглÑниÑе еÑÑ Ñаз на запÑоÑ, ÑигÑÑиÑовавÑий в ÐодÑазделе 68.2.1, но на ÑÑÐ¾Ñ Ñаз Ñо ÑпиÑком MCV, ÑозданнÑм по Ñем же ÑÑолбÑам (ÑÑнкÑионалÑнÑе завиÑимоÑÑи нÑжно ÑдалиÑÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð»Ð°Ð½Ð¸ÑовÑик мог иÑполÑзоваÑÑ ÑолÑко новÑÑ ÑÑаÑиÑÑикÑ).
DROP STATISTICS stts;
CREATE STATISTICS stts2 (mcv) ON a, b FROM t;
ANALYZE t;
EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 1;
QUERY PLAN
-------------------------------------------------------------------â------------
Seq Scan on t (cost=0.00..195.00 rows=100 width=8) (actual rows=100 loops=1)
Filter: ((a = 1) AND (b = 1))
Rows Removed by Filter: 9900ÐÑенка оказÑваеÑÑÑ Ñакой же ÑоÑной, как и Ñ ÑÑнкÑионалÑнÑми завиÑимоÑÑÑми, во многом благодаÑÑ ÑомÑ, ÑÑо ÑаблиÑа доÑÑаÑоÑно мала и Ñ Ð°ÑакÑеÑизÑеÑÑÑ Ð¿ÑоÑÑÑм ÑаÑпÑеделением Ñ Ð½ÐµÐ±Ð¾Ð»ÑÑим колиÑеÑÑвом ÑникалÑнÑÑ Ð·Ð½Ð°Ñений. ÐÑежде Ñем пеÑейÑи ко вÑоÑÐ¾Ð¼Ñ Ð·Ð°Ð¿ÑоÑÑ, в коÑоÑом ÑÑнкÑионалÑнÑе завиÑимоÑÑи показали ÑÐµÐ±Ñ Ð½Ðµ оÑÐµÐ½Ñ Ñ Ð¾ÑоÑо, давайÑе пÑоÑмоÑÑим ÑпиÑок MCV.
ÐÑоÑмоÑÑеÑÑ ÑпиÑок MCV можно Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð²Ð¾Ð·Ð²ÑаÑаÑÑей множеÑÑво ÑÑнкÑии pg_mcv_list_items.
SELECT m.* FROM pg_statistic_ext join pg_statistic_ext_data on (oid = stxoid),
pg_mcv_list_items(stxdmcv) m WHERE stxname = 'stts2';
index | values | nulls | frequency | base_frequency
-------+----------+-------+-----------+----------------
0 | {0, 0} | {f,f} | 0.01 | 0.0001
1 | {1, 1} | {f,f} | 0.01 | 0.0001
...
49 | {49, 49} | {f,f} | 0.01 | 0.0001
50 | {50, 50} | {f,f} | 0.01 | 0.0001
...
97 | {97, 97} | {f,f} | 0.01 | 0.0001
98 | {98, 98} | {f,f} | 0.01 | 0.0001
99 | {99, 99} | {f,f} | 0.01 | 0.0001
(100 rows) ÐолÑÑÐµÐ½Ð½Ð°Ñ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¿Ð¾Ð´ÑвеÑждаеÑ, ÑÑо два ÑÑолбÑа ÑодеÑÐ¶Ð°Ñ 100 ÑникалÑнÑÑ
комбинаÑий знаÑений и ÑÑо ÑÑи ÑÑолбÑÑ ÑкоÑее вÑего ÑÐ°Ð²Ð½Ñ (ÑаÑÑоÑа каждой комбинаÑии â 1%). ÐÐ°Ð·Ð¾Ð²Ð°Ñ ÑаÑÑоÑа вÑÑиÑлÑеÑÑÑ, иÑÑ
Ð¾Ð´Ñ Ð¸Ð· ÑаÑÑÐ¾Ñ Ð·Ð½Ð°Ñений оÑделÑнÑÑ
ÑÑолбÑов, без ÑÑÑÑа налиÑÐ¸Ñ ÑÑаÑиÑÑики по неÑколÑким ÑÑолбÑам. ÐÑли Ð±Ñ Ð² одном из ÑÑолбÑов оказалиÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NULL, ÑÑо бÑло Ð±Ñ Ð¾ÑÑажено в ÑÑолбÑе nulls.
ÐÑÐµÐ½Ð¸Ð²Ð°Ñ Ð¸Ð·Ð±Ð¸ÑаÑелÑноÑÑÑ, планиÑовÑик пÑименÑÐµÑ Ð²Ñе ÑÑÐ»Ð¾Ð²Ð¸Ñ Ðº ÑлеменÑам ÑпиÑка MCV и ÑÑммиÑÑÐµÑ ÑаÑÑоÑÑ ÑÐµÑ , коÑоÑÑе ÑÑим ÑÑловиÑм ÑдовлеÑвоÑÑÑÑ.
Ð ÑÑавнении Ñ ÑÑнкÑионалÑнÑми завиÑимоÑÑÑми ÑпиÑки MCV имеÑÑ Ð´Ð²Ð° важнÑÑ Ð¿ÑеимÑÑеÑÑва. Ðо-пеÑвÑÑ , в ÑÑÐ¸Ñ ÑпиÑÐºÐ°Ñ Ñ ÑанÑÑÑÑ ÑакÑиÑеÑкие знаÑениÑ, ÑÑо позволÑÐµÑ Ð¾Ð¿ÑеделиÑÑ, какие комбинаÑии ÑвлÑÑÑÑÑ ÑовмеÑÑимÑми.
EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a = 1 AND b = 10;
QUERY PLAN
-------------------------------------------------------------------â--------
Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0 loops=1)
Filter: ((a = 1) AND (b = 10))
Rows Removed by Filter: 10000Ðо-вÑоÑÑÑ , ÑпиÑки MCV Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑ Ð´Ð»Ñ Ð±Ð¾Ð»ÐµÐµ ÑиÑокого аÑÑоÑÑименÑа ÑÑловий, а не ÑолÑко Ð´Ð»Ñ ÑÑавнений, как ÑÑнкÑионалÑнÑе завиÑимоÑÑи. ÐапÑимеÑ, взглÑниÑе на запÑÐ¾Ñ Ñ Ð´Ð¸Ð°Ð¿Ð°Ð·Ð¾Ð½Ð¾Ð¼ знаÑений, вÑполнÑемÑй Ñ Ñой же ÑаблиÑей:
EXPLAIN (ANALYZE, TIMING OFF) SELECT * FROM t WHERE a <= 49 AND b > 49;
QUERY PLAN
-------------------------------------------------------------------â--------
Seq Scan on t (cost=0.00..195.00 rows=1 width=8) (actual rows=0 loops=1)
Filter: ((a <= 49) AND (b > 49))
Rows Removed by Filter: 10000