開始
參考momjian 的文章:
http://momjian.us/main/writings/pgsql/optimizer.pdf
首先,構造一個數據分布明顯傾斜的表(有的值占據了70%以上的分布)
postgres=# CREATE TEMPORARY TABLE sample (letter, junk) AS postgres-# SELECT substring(relname, 1, 1), repeat('x', 250) postgres-# FROM pg_class postgres-# ORDER BY random(); SELECT 291 postgres=# postgres=# CREATE INDEX i_sample on sample (letter); CREATE INDEX postgres=#
postgres=# CREATE OR REPLACE FUNCTION lookup_letter(text) RETURNS SETOF text AS $$ postgres$# BEGIN postgres$# RETURN QUERY EXECUTE' postgres$# EXPLAIN SELECT letter postgres$# FROM sample postgres$# WHERE letter ='''||$1||''''; postgres$# END postgres$# $$ LANGUAGE plpgsql; CREATE FUNCTION postgres=# postgres=# WITH letters (letter, count) AS ( postgres(# SELECT letter, COUNT(*) postgres(# FROM sample postgres(# GROUP BY 1 postgres(# ) postgres-# SELECT letter, count, (count * 100.0 / (SUM(count) OVER ()))::numeric(4,1) AS "%" postgres-# FROM letters postgres-# ORDER BY 2 DESC; letter | count | % --------+-------+------ p | 223 | 76.6 c | 12 | 4.1 s | 9 | 3.1 r | 8 | 2.7 f | 6 | 2.1 d | 5 | 1.7 u | 5 | 1.7 _ | 5 | 1.7 t | 5 | 1.7 v | 4 | 1.4 e | 3 | 1.0 a | 3 | 1.0 i | 2 | 0.7 k | 1 | 0.3 (14 rows) postgres=#
此時,如果不通過 analyze 來更新統計信息,得到的 執行計划是不准確的。所以先要更新統計信息:
postgres=#analyze sampel;
postgres=#
然后,再來看執行的情況:
[作者:技術者高健@博客園 mail: luckyjackgao@gmail.com ]
postgres=# EXPLAIN SELECT * FROM sample WHERE letter ='p'; QUERY PLAN ----------------------------------------------------------- Seq Scan on sample (cost=0.00..14.64 rows=223 width=256) Filter: (letter = 'p'::text) (2 rows) postgres=# postgres=# EXPLAIN SELECT * FROM sample WHERE letter = 'd'; QUERY PLAN ----------------------------------------------------------------------- Bitmap Heap Scan on sample (cost=4.29..14.24 rows=5 width=256) Recheck Cond: (letter = 'd'::text) -> Bitmap Index Scan on i_sample (cost=0.00..4.29 rows=5 width=0) Index Cond: (letter = 'd'::text) (4 rows) postgres=# postgres=# EXPLAIN SELECT * FROM sample WHERE letter = 'k'; QUERY PLAN ------------------------------------------------------------------------- Index Scan using i_sample on sample (cost=0.00..8.27 rows=1 width=256) Index Cond: (letter = 'k'::text) (2 rows) postgres=#
數據分布很大(比如70%以上),用index scan 已經沒有意義了,因為數據太多了。所以就不如用 全表掃描了。
數據分布較小(比如 1.7%),則用 bitmap index scan。數據更少的時候,用的是 index scan。
需要引起注意的是, bitmap index 也可以用在where 條件單一的時候。
結束