8

我想利用在Postgres的僅索引掃描的電源,並與一個表實驗:爲什麼真空分析不能分析變更查詢計劃?

CREATE TABLE dest.contexts 
(
    id integer NOT NULL, 
    phrase_id integer NOT NULL, 
    lang character varying(5) NOT NULL, 
    ranking_value double precision, 
    index_min integer, 
    index_max integer, 
    case_sensitive boolean, 
    is_enabled boolean, 
    is_to_sync boolean NOT NULL DEFAULT true 
); 

insert into dest.contexts select * from source.contexts; 

alter table dest.contexts 
    add constraint pk_contexts primary key (id, phrase_id, lang); 

CREATE INDEX idx_contexts_ 
    ON dest.contexts 
    USING btree 
    (id, is_enabled, lang, phrase_id, ranking_value, index_min, index_max, case_sensitive); 

該指數涵蓋我想在接下來的查詢中使用的所有列:

explain analyze 
select ranking_value, index_min, index_max, case_sensitive 
from dest.contexts 
where id = 456 and is_enabled 

我立即檢查方案生成後:

Bitmap Heap Scan on contexts (cost=4.41..31.46 rows=12 width=17) (actual time=0.045..0.045 rows=0 loops=1) 
    Recheck Cond: (id = 456) 
    Filter: is_enabled 
    -> Bitmap Index Scan on idx_contexts_ (cost=0.00..4.40 rows=12 width=0) (actual time=0.038..0.038 rows=0 loops=1) 
     Index Cond: ((id = 456) AND (is_enabled = true)) 
Planning time: 0.631 ms 
Execution time: 0.093 ms 

令人奇怪的是,但行...

在幾秒鐘它改變到另一個

Index Scan using pk_contexts on contexts (cost=0.28..17.93 rows=6 width=17) (actual time=0.027..0.027 rows=0 loops=1) 
    Index Cond: (id = 456) 
    Filter: is_enabled 
Planning time: 0.185 ms 
Execution time: 0.070 ms 

我試圖迫使它使用僅索引掃描(自動清理?):

analyze dest.contexts 

但它不會改變任何東西。然後,我做

vacuum verbose analyze dest.contexts; 

INFO: vacuuming "dest.contexts" 
INFO: index "pk_contexts" now contains 4845 row versions in 21 pages 
DETAIL: 0 index row versions were removed. 
0 index pages have been deleted, 0 are currently reusable. 
CPU 0.00s/0.00u sec elapsed 0.00 sec. 
INFO: index "idx_contexts_" now contains 4845 row versions in 37 pages 
DETAIL: 0 index row versions were removed. 
0 index pages have been deleted, 0 are currently reusable. 
CPU 0.00s/0.00u sec elapsed 0.00 sec. 
INFO: "contexts": found 0 removable, 4845 nonremovable row versions in 41 out of 41 pages 
DETAIL: 0 dead row versions cannot be removed yet. 
There were 0 unused item pointers. 
0 pages are entirely empty. 
CPU 0.00s/0.00u sec elapsed 0.00 sec. 
INFO: analyzing "dest.contexts" 
INFO: "contexts": scanned 41 of 41 pages, containing 4845 live rows and 0 dead rows; 4845 rows in sample, 4845 estimated total rows 

在這裏,我終於得到了我想要的:

Index Only Scan using idx_contexts_ on contexts (cost=0.28..4.40 rows=6 width=17) (actual time=0.014..0.014 rows=0 loops=1) 
    Index Cond: ((id = 456) AND (is_enabled = true)) 
    Filter: is_enabled 
    Heap Fetches: 0 
Planning time: 0.247 ms 
Execution time: 0.052 ms 

所以這裏的問題:

  1. 爲什麼不analyze教它用寬大的「全「覆蓋」索引?
  2. 爲什麼vacuum analyze這樣做?
  3. 我的桌子是用一個大插入物從頭開始填充的。爲什麼vacuum什麼都做?在我看來,這裏沒有任何東西可以吸引。
+2

https://www.postgresql.org/docs/9.6/static/routine-vacuuming.html#VACUUM-FOR-VISIBILITY-MAP可能是原因。 – wildplasser

回答

0

分析負責收集統計信息,並分析查詢計劃和計劃成本選擇的影響。

索引不包含關於元組的可見性信息。因此,儘管select中的所有列都位於索引中,但還是應用讀取數據頁面和過濾結果集的事件。如果所有的元組在頁面中可見,Postgres不需要額外的過濾操作。 Postgres使用可見性映射(vm)來實現這一點。

真空使用並更新可見性圖,同時回收死元組。因此,如果可能,vacuum會更改查詢計劃以使用僅索引掃描。

https://www.postgresql.org/docs/9.6/static/sql-vacuum.html

https://www.postgresql.org/docs/9.6/static/storage-vm.html