Postgresql
索引不用於日期範圍條件
我是這樣查詢的:
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 無法使用索引來檢查您的狀況。因此,請繼續使用您的原始查詢。