我有幾百萬行稱爲項目的列看起來像這樣的一個表:PostgreSQL的指數不使用
CREATE TABLE item (
id bigint NOT NULL,
company_id bigint NOT NULL,
date_created timestamp with time zone,
....
)
有此表是經常搜索的COMPANY_ID
CREATE INDEX idx_company_id ON photo USING btree (company_id);
指數某個客戶的最後10個項目,即
SELECT * FROM item WHERE company_id = 5 ORDER BY date_created LIMIT 10;
目前,有一個客戶accoun對於該表中約75%的數據,其他25%的數據分佈在25個左右的其他客戶,這意味着75%的行具有5的公司ID,其他行的公司id在6和25.
對於除了主要公司(id = 5)之外的所有公司,查詢通常運行速度非常快。我可以理解爲什麼自上COMPANY_ID指數可用於公司除了5
我有不同的索引嘗試使搜索更有效的爲公司5,似乎最有意義的一個是
CREATE INDEX idx_date_created
ON item (date_created DESC NULLS LAST);
如果我添加了這個索引,對於主要公司(id = 5)的查詢得到了很大的改善,但是對所有其他公司的查詢都變成廢話。
解釋一些結果分析公司ID 5 & 6使用和不使用新的索引:
公司ID 5
新的索引
QUERY PLAN
Limit (cost=214874.63..214874.65 rows=10 width=639) (actual time=10481.989..10482.017 rows=10 loops=1)
-> Sort (cost=214874.63..218560.33 rows=1474282 width=639) (actual time=10481.985..10481.994 rows=10 loops=1)
Sort Key: photo_created
Sort Method: top-N heapsort Memory: 35kB
-> Seq Scan on photo (cost=0.00..183015.92 rows=1474282 width=639) (actual time=0.009..5345.551 rows=1473561 loops=1)
Filter: (company_id = 5)
Rows Removed by Filter: 402513
Total runtime: 10482.075 ms
之前之後的新指標:
QUERY PLAN
Limit (cost=0.43..1.98 rows=10 width=639) (actual time=0.087..0.120 rows=10 loops=1)
-> Index Scan using idx_photo__photo_created on photo (cost=0.43..228408.04 rows=1474282 width=639) (actual time=0.084..0.099 rows=10 loops=1)
Filter: (company_id = 5)
Rows Removed by Filter: 26
Total runtime: 0.164 ms
公司編號6
新的索引之前:
QUERY PLAN
Limit (cost=2204.27..2204.30 rows=10 width=639) (actual time=0.044..0.053 rows=3 loops=1)
-> Sort (cost=2204.27..2207.55 rows=1310 width=639) (actual time=0.040..0.044 rows=3 loops=1)
Sort Key: photo_created
Sort Method: quicksort Memory: 28kB
-> Index Scan using idx_photo__company_id on photo (cost=0.43..2175.96 rows=1310 width=639) (actual time=0.020..0.026 rows=3 loops=1)
Index Cond: (company_id = 6)
Total runtime: 0.100 ms
後的新指數:
QUERY PLAN
Limit (cost=0.43..1744.00 rows=10 width=639) (actual time=0.039..3938.986 rows=3 loops=1)
-> Index Scan using idx_photo__photo_created on photo (cost=0.43..228408.04 rows=1310 width=639) (actual time=0.035..3938.975 rows=3 loops=1)
Filter: (company_id = 6)
Rows Removed by Filter: 1876071
Total runtime: 3939.028 ms
我已經運行一個完整的真空和分析有關表格,讓PostgreSQL的應該有向上的最新統計數據。任何想法如何讓PostgreSQL爲被查詢的公司選擇正確的索引?
我的猜測是'LIMIT'是作弊。但是如果你用'ANALYZE'提供'EXPLAIN'會更清楚,它將幫助我們檢查用於規劃者的表格統計信息。順便說一句,你是否正在運行'VACUUM ANALYZE'? –
有多少獨特的'company_id'?表中有多少百分比是'company_id = 5'? – jmelesky
編輯我的帖子以添加更多詳細信息,感謝您的幫助 – Mike