除了索引之外,我還需要統計資訊嗎?
假設我有一張包含應該經過幾個步驟的圖像的表格:
CREATE TABLE images (filename text, extracted bool, cropped bool, resized bool); INSERT INTO images (filename, extracted, cropped, resized) VALUES ('foo', false, false, false), ('bar', true, false, false), ('baz', true, true, false), ('qux', true, true, true);
在某些時候,我有一個查詢來查找所有被裁剪但仍需要調整大小的圖像:
SELECT count(*) FROM images WHERE cropped AND NOT resized;
現在我相信使查詢快速的最好方法是部分索引:
CREATE INDEX ON images (cropped, resized) WHERE (cropped AND NOT resized);
我將其設為局部,因為這
cropped AND NOT resized
是一種相對罕見的狀態,而可能有數百萬張圖像已經完全處理,還有數百萬張圖像尚未裁剪。我現在的問題是,除了索引之外,我還需要統計資訊嗎?
其中之一?
CREATE STATISTICS stat1 (dependencies) ON cropped, resized FROM images; CREATE STATISTICS stat2 (ndistinct) ON cropped, resized FROM images; CREATE STATISTICS stat3 (mcv) ON cropped, resized FROM images; ANALYZE images;
我找到了我之前錯過的章節How the Planner Uses Statistics (或者更確切地說與Planner 使用的統計資訊混為一談),但它只討論瞭如何將統計資訊轉換為行估計。鑑於顯然沒有關於索引的統計數據,我不清楚如何選擇索引。
我的實驗表明,目前我似乎不需要這些統計數據來使用索引,但仍不清楚為什麼會這樣。在深入了解原始碼後,我想我可以回答我自己的問題。
本質上,使用索引的決定是
btcostestimate()
依次做出的genericcostestimate()
。它有助於記住每個表可以使用哪些類型的統計資訊:
- 元組數
- 對於每一列:不同值的數量(有時稱為“基數”)
- 對於每一列:最常見的值
- 對於每一列:剩餘(不太常見)值的直方圖
- 如果已配置:
dependencies
stats(“A 列中有多少個值只有一個值出現在 B 列中。”)- 如果已配置:
ndistinct
統計資訊(A 和 B 列中唯一值組合的數量。)- 如果已配置:
mcv
統計資訊(A 和 B 列中最常見的值組合。)對於每個索引,Postgres 確定可以使用索引檢查哪些條件(“索引條件”或“索引質量”)。基於這些,
genericcostestimate()
(使用clauselist_selectivity()
)計算索引的選擇性,同時考慮到那些擴展的統計數據。這實際上反映在我的實驗中,因為我通過以下mcv
類型的擴展統計數據獲得了更好的行估計:實際時間的差異取決於記憶體。
部分索引的謂詞也會被考慮在內,但前提是它引入了額外的限制,所以這裡不相關。
所以我認為如何選擇索引是這樣的:首先檢查索引謂詞以查看索引是否可用。然後計算特定條件的選擇性,如果沒有擴展統計數據,這確實有點錯誤。但再往下看,當計算實際成本時,它是如此之低,因為索引太小,以至於即使錯誤的行估計成本也非常低。
所以答案是肯定的,對於良好的行估計仍然需要理論上擴展的統計資訊,****但也不需要,仍然選擇沒有擴展統計資訊的索引,因為它太小了。
你在很大程度上想多了。您的查詢非常簡單,只有幾種方法可以執行。無論是返回 7000 行還是 2000 行,都無關緊要,因為無論哪種方式,索引似乎都比微不足道的替代方案要好。
如果您確實想要執行更多種類的查詢,這些查詢有更多機會做出錯誤的規劃器選擇,那麼包含 mcv 種類的擴展統計資訊可能很重要。
你的兩個例子完全不匹配。您問題中的計數表會導致行估計與您的答案中顯示的大不相同。如果沒有擴展的 MCV 統計資訊,它將提供大約 5,000,000,如果有擴展的統計資訊,它將提供大約 1。當然不是 6872 對 1782。