无法达到条件表达指数

时间:2016-01-08 11:50:50

标签: postgresql

我有一个包含大约2000万条记录的表,其索引超过created_at时间戳字段。索引的大小很大,即使使用索引扫描,通过该字段查询表也不够快(7秒)。所以我决定用较小的表达索引来玩。事情是计划者永远不会打他们,而是进行顺序扫描。我做错了什么?

db=# SELECT COUNT(*) FROM xxx;
 count
----------
 19527175
(1 row)

条件表达指数定义为:

CREATE INDEX xxx_idx ON xxx (DATE(created_at)) WHERE created_at > '2016-01-01';

该分数仅占整个数据的2%。

db=# SELECT COUNT(*) FROM xxx WHERE created_at > '2016-01-01';
 count
---------
 335895
(1 row)

然而,当通过指定相同的条件表达式来尝试使用索引时,会使用顺序扫描。

db=# EXPLAIN ANALYZE SELECT * FROM xxx WHERE DATE(created_at) > '2016-01-01';
                              QUERY PLAN
-----------------------------------------------------------------------
 Seq Scan on xxx  (cost=0.00..1533675.37 rows=6509853 width=884) (actual time=23.104..120704.554 rows=319278 loops=1)
   Filter: (date(created_at) > '2016-01-01'::date)
   Rows Removed by Filter: 19208882
 Planning time: 0.245 ms
 Execution time: 120748.839 ms
(5 rows)

1 个答案:

答案 0 :(得分:1)

您混淆了查询中的created_at用法(使用DATE(created_at))和索引定义。

为了确保您的所有查询都使用您的索引(使用index only scan),您应该在索引'中使用相同的表达式/列。表达式和索引中的表达式WHERE子句(partial index)。

F.ex:

CREATE INDEX xxx_idx ON xxx (DATE(created_at)) WHERE DATE(created_at) > '2015-12-01';

SQLFiddle

然后,如果您查询DATE(created_at)将使用索引 - 最有可能的是:当PostgreSQL的引擎确定顺序时,它仍然有可能不会被使用扫描更快(索引将在significantly smaller than its table时使用)。

只有在明确过滤索引时,才会使用原始索引。 WHERE条款也是DATE(created_at) > '2015-12-01' AND created_at > '2015-12-01'

SQLFiddle