2015-09-01 29 views
1
PostgreSQL 9.2 

我有如下表(tbl):如何創建索引以避免與DISTINCT一起使用排序步驟?

------------------------------------------------------------- 
| id | mailing_id | recipient_id | delivery_state_id | 
------------------------------------------------------------- 
| PK | integer |  integer |  integer  | 
------------------------------------------------------------- 

而且,我創建了以下指標:

CREATE INDEX idx_name 
    ON tbl 
    USING btree 
    (recipient_id); 

因爲在posgtresql指標都有默認的排序,我預計查詢

SELECT DISTINCT recipient_id 
FROM tbl 

可以避免排序步驟。但運行

EXPLAIN ANALYZE SELECT DISTINCT recipient_id 
FROM mailing.mailing_recipient mr 

告訴我,它不能:

Unique (cost=1401370.66..1442288.31 rows=145798 width=4) (actual time=9377.410..11388.869 rows=1037472 loops=1) 
    -> Sort (cost=1401370.66..1421829.48 rows=8183530 width=4) (actual time=9377.408..10849.160 rows=8183160 loops=1) 
     Sort Key: recipient_id 
     Sort Method: external merge Disk: 111968kB 
     -> Seq Scan on tbl (cost=0.00..126072.30 rows=8183530 width=4) (actual time=0.008..1073.771 rows=8183160 loops=1) 
Total runtime: 11448.373 ms 

正如你所看到的,仍然有排序。

問題:如何創建索引以避免排序步驟?

+0

只是一個猜測,但你也試圖通過'選擇recipient_id' recipient_id FROM TBL組由recipient_id訂單?大多數情況下,任何「distinct」,「group by」或「order by」最終都會進行排序,但我同意btree索引的默認排序應該允許優化器使用它來獲得您的優勢。 – SlimsGhost

+0

@SlimsGhost在GordonLinoff的回答後嘗試。也不起作用。我猜postgresql使用where索引所需的索引掃描索引... –

+0

recipient_id是否被約束爲NOT NULL? –

回答

1

唉,這太長了評論。

這讓我感到驚訝;我希望Postgres比這更聰明。這個版本會發生什麼?

SELECT recipient_id 
FROM tbl 
GROUP BY recipient_id; 

你使用的是什麼版本的Postgres? Postgres在9.2版本中引入了僅索引掃描(請參閱here),這可能解釋了缺少索引的使用。我可以說,索引掃描用於9.3中的distinct

這裏是9.3類似的查詢(select distinct totalprice from orders)的解釋:

Unique (cost=0.42..5505.62 rows=2794 width=8) 
    -> Index Only Scan using idx_orders_totalprice on orders (cost=0.42..5023.16 rows=192983 width=8)" 
+0

無法使用Group - > Sort - > Sort key:recipient_id'。也許我需要以某種特殊的方式創建索引?我重新檢查列的索引存在.... –

+0

順便說一句,postgresql使用索引,當我設置不太高的「限制」。例如'limit 2000'使用索引,但是'limit 10000'不使用索引。 –

+0

這是9.2,Gordon –

相關問題