如何在 Postgres 中使用 WHERE 子句添加索引

Kat*_*amy 6 postgresql indexing where-clause

我想WHERE在 Postgres 中添加一个带有子句的索引。我使用以下查询来执行此操作:

create index concurrently em_openorder_idx on line (m_product_id, org_id, date) where date >= now() - 90
Run Code Online (Sandbox Code Playgroud)

但我收到以下错误:

functions in index predicate must be marked IMMUTABLE
Run Code Online (Sandbox Code Playgroud)

Nic*_*nes 6

子句中的表达式WHERE必须是不可变的,即对于给定的一组参数,每次调用它时都必须返回相同的值。now()显然不符合条件。

您可以像这样索引过去 90 天的数据:

create index concurrently em_openorder_idx on line (m_product_id,org_id,date) 
where date>='now'::date-90
Run Code Online (Sandbox Code Playgroud)

但是,如果您返回并查看索引定义,您会发现它已转换为常量表达式:

... WHERE date >= ('2016-03-02'::date - 90);
Run Code Online (Sandbox Code Playgroud)

换句话说,这个90天的窗口不会随着时间的推移而自动向前推进;您需要定期删除并重新创建该索引。

date另一件需要注意的事情是,您的查询只有在与不可变表达式进行比较时才能使用此索引。例如,这里将使用索引:

SELECT * FROM line WHERE date = '2016-03-02';
Run Code Online (Sandbox Code Playgroud)

...但不能在这里使用:

SELECT * FROM line WHERE date = CURRENT_DATE;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您使用的是 Postgres 9.5,则该表可能是BRIN 索引的良好候选者。


Jua*_*eza 1

只需创建索引

create index concurrently em_openorder_idx on line (m_product_id,org_id,date)
Run Code Online (Sandbox Code Playgroud)

我猜你想实现一个与此类似的查询

EXPLAIN ANALYZE
SELECT *
FROM line
WHERE m_product_id = @id
  AND date>=now()-90
Run Code Online (Sandbox Code Playgroud)

这将使用索引并且应该非常快。