PostgreSQL:使用了索引 - 但在使用LIMIT OFFSET查询时却没有

时间:2017-12-27 22:07:45

标签: sql postgresql select indexing

假设我在PostgreSQL数据库中有一个包含许多条目的messages表。该表的主键只是一个简单的serial列(如int,但带有“自动增量”)。

然后我想选择用户收到并符合特定条件的TOP-25消息。结果按唯一主键列(msgid DESC)排序。

-- EXPLAIN ANALYZE
SELECT msgid, msgtype, created, msgtitle, recvuser, readbyrecv, someothercolumn, onemorecolumn
FROM xyz.messages 
WHERE ( ( msgtype = 42 ) OR ( msgtype = 1337 ) ) 
  AND ( recvuser = 123 ) AND ( hiddenbyrecv = false ) 
ORDER BY msgid DESC 
LIMIT 25 OFFSET 0

我有一个像这样的过滤索引:

CREATE INDEX ix_abcde
ON xyz.messages
USING btree (msgtype, recvuser, hiddenbyrecv, msgid DESC)
WHERE (msgtype = 42 OR msgtype = 1337) AND hiddenbyrecv = false;

我认为索引应该包含WHEREORDER子句中使用的所有列。

如果我运行SELECT 而不用 LIMIT 25 OFFSET 0(该行已注释掉),则正在使用索引并且查询非常快(大约2ms) ):

-- EXPLAIN ANALYZE
SELECT msgid, msgtype, created, msgtitle, recvuser, readbyrecv, someothercolumn, onemorecolumn
FROM xyz.messages 
WHERE ( ( msgtype = 42 ) OR ( msgtype = 1337 ) ) 
  AND ( recvuser = 123 ) AND ( hiddenbyrecv = false ) 
ORDER BY msgid DESC 
-- LIMIT 25 OFFSET 0

但是如果我使用来查询 LIMIT和OFFSET子句(请参阅第一个SQL查询),它会向后扫描表的主键并执行全表扫描。索引未使用。该查询的时间超过 100倍(> 200ms)。

由于msgid是唯一的(主键),我认为PostgreSQL应该能够使用索引确定性地找到此列所排序的TOP 25条目。我按正确的顺序在索引中包含了唯一的ORDER BY列。

我错过了什么?你能给我一些提示吗?

//编辑:服务器从Debian存储库运行标准的PostgreSQL 9.4版本包。

0 个答案:

没有答案