Postgresql

索引不用於日期範圍條件

  • April 5, 2022

我是這樣查詢的:

SELECT count(*)
FROM orders
WHERE planned_shipping_date >= '2022-04-04'
AND planned_shipping_date < '2022-04-05'

然後我遇到了這個答案,因為在更複雜的查詢中它使查詢更容易閱讀,我重寫了這樣的查詢:

SELECT count(*)
FROM orders
WHERE planned_shipping_date <@ daterange('2022-04-04', '2022-04-05')

我相信它們在語義上是相同的,但看看這些計劃:

Aggregate  (cost=76.91..76.92 rows=1 width=8) (actual time=1.066..1.068 rows=1 loops=1)
 ->  Index Only Scan using orders_planned_shipping_date_idx on orders  (cost=0.29..69.73 rows=2872 width=0) (actual time=0.067..0.646 rows=2813 loops=1)
       Index Cond: ((planned_shipping_date >= '2022-04-04'::date) AND (planned_shipping_date < '2022-04-05'::date))
       Heap Fetches: 0
Aggregate  (cost=2753.57..2753.58 rows=1 width=8) (actual time=18.309..18.311 rows=1 loops=1)
 ->  Index Only Scan using orders_planned_shipping_date_idx on orders  (cost=0.29..2751.93 rows=655 width=0) (actual time=17.520..18.132 rows=2813 loops=1)
       Filter: (planned_shipping_date <@ '[2022-04-04,2022-04-05)'::daterange)
       Rows Removed by Filter: 128138
       Heap Fetches: 0

日期範圍的使用似乎排除了索引的使用。

我需要不同的索引還是不應該使用這樣的日期範圍?

是的,您的查詢在語義上是相同的,但語法也很重要。

為了得到索引的支持,WHERE條件必須如下所示:

***<indexed expression>*** ***<operator>*** ***<constant>***

  • ***<indexed expression>***是什麼用於CREATE INDEX
  • ***<operator>***是索引的運算符類中的運算符
  • ***<constant>***在索引掃描期間必須保持不變(至少STABLE

此外,PostgreSQL 知道允許它在某些其他情況下使用索引掃描的支持函式,但這並不適用於此。

您的問題是 operator <@,它不受 B-tree 索引的支持。因此,PostgreSQL 無法使用索引來檢查您的狀況。因此,請繼續使用您的原始查詢。

引用自:https://dba.stackexchange.com/questions/310530