2017-03-08 52 views
2

我有一个表产品推荐合适的索引上我的数据库

Product(id BIGINT, 
     ... Some more columns here 
     expired DATE); 

我想更快的检索创建过期字段索引。

的大部分时间我的where子句

 ... 
     WHERE (expired IS NULL OR expired > now()); 

请你可以建议哪些指标更适合我。

当我执行讲解分析上面的查询

EXPLAIN ANALYZE 
SELECT 1 
FROM product 
WHERE (expired IS NULL) OR (expired > now()); 

它给了我下面的结果。其中它没有使用我创建的索引。

Seq Scan on product (cost=0.00..190711.22 rows=5711449 width=0) (actual time=0.009..8653.380 rows=7163105 loops=1) 
    Filter: ((expired IS NULL) OR (expired > now())) 
     Rows Removed by Filter: 43043 
    Planning time: 0.117 ms 
Execution time: 15679.478 ms 
(5 rows) 

我想那是因为“或”的条件。我试图创建函数库索引,但它给了我下面的错误

ERROR: functions in index expression must be marked IMMUTABLE 

有没有我们可以做任何替代办法?

回答

1

,则应该更换WHERE条款看起来像这样:

... WHERE COALESCE(expired, DATE 'infinity') > current_date; 

这equivalen吨至您的查询,但现在你可以使用以下指标:

CREATE INDEX ON product (COALESCE(expired, DATE 'infinity')); 
+0

天哪,我有同样的想法:D但没有发布,因为它感觉有点hacky。 – pozs

+0

我认为这是一种恭维:^) –

1

可能默认的B树索引是最适合你的;散列索引只处理“等于”比较,主旨和GIN索引对于更复杂的数据类型是什么,你正在使用:

https://www.postgresql.org/docs/current/static/indexes-types.html

其实B树是默认的,所以你需要做的是一样的东西:

CREATE INDEX Products_expired_idx ON TABLE Products (expired) 
+0

当我解释一下简单的分析与查询我cluase给它不喜欢利用序列 –

+0

扫描索引产品(成本= 0.00..190711.22行 过滤器:((expired IS NULL)OR(expired> now())) 过滤器删除的行数:43043 计划时间:过期时间= 0.09到8653.380行= 7163105循环= 1) 0.117毫秒 执行时间:15679.478毫秒 (5行) –

+0

即使您有一个,查询计划人员也可以选择不使用索引;请参阅https://robots.thoughtbot.com/why-postgres-wont-always-use-an-index以获得很好的解释。如果您的统计信息已过期,则可以运行''VACUUM FULL Products''并再次尝试查询。 –