Postgresql 在我的数据库上建议适当的索引

Postgresql 在我的数据库上建议适当的索引,postgresql,indexing,Postgresql,Indexing,我有一个餐桌用品 Product(id BIGINT, ... Some more columns here expired DATE); 我想在过期字段上创建索引,以便更快地检索 大多数情况下,我的where子句是 ... WHERE (expired IS NULL OR expired > now()); 请你建议哪个指数更适合我 当我为上述查询执行explain ANALYSE时 EXPLAIN ANALYZ

我有一个餐桌用品

Product(id  BIGINT,
         ... Some more columns here
         expired  DATE);
我想在过期字段上创建索引,以便更快地检索

大多数情况下,我的where子句是

       ...
       WHERE  (expired IS NULL OR expired > now());
请你建议哪个指数更适合我

当我为上述查询执行explain ANALYSE时

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

我们有没有其他办法呢?

也许默认的B树索引最适合您;散列索引只处理“等于”比较,GiST和GIN索引适用于您正在使用的更复杂的数据类型:

事实上,B-树是默认的,因此您需要做的是:

CREATE INDEX Products_expired_idx ON TABLE Products (expired)

您应该将
WHERE
子句更改为如下所示:

... WHERE COALESCE(expired, DATE 'infinity') > current_date;
这相当于您的查询,但现在您可以使用以下索引:

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

当我用CLUSE解释分析过的简单查询时,我给出了它没有在产品上使用像ESEQ扫描这样的索引(成本=0.00..190711.22行=5711449宽度=0)(实际时间=0.009..8653.380行=7163105循环=1)过滤器:((过期为空)或(过期>现在())过滤器删除的行:43043计划时间:0.117毫秒执行时间:15679.478毫秒(5行)即使您有索引,查询计划员也可以选择不使用该索引;请参阅以获得良好的解释。如果您的统计数据已过期,您可以运行
真空满产品
,然后重试查询。真空满但未成功。我想这是因为“或”条件。@GaneshJadhav您有7M+行,其中43K行被谓词过滤掉。有了这些统计信息,PostgreSQL很可能会选择seq.scan(因为它几乎需要所有行)。