2015-09-01 25 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 –

相关问题