索引不用于日期范围条件

And*_*eKR 4 postgresql index range-types

我是这样查询的:

SELECT count(*)
FROM orders
WHERE planned_shipping_date >= '2022-04-04'
AND planned_shipping_date < '2022-04-05'
Run Code Online (Sandbox Code Playgroud)

然后我遇到了这个答案,因为在更复杂的查询中它使查询更容易阅读,所以我重写了查询,如下所示:

SELECT count(*)
FROM orders
WHERE planned_shipping_date <@ daterange('2022-04-04', '2022-04-05')
Run Code Online (Sandbox Code Playgroud)

我相信它们在语义上是相同的,但看看计划:

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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

日期范围的使用似乎排除了索引的使用。

我是否需要不同的索引,或者我不应该使用这样的日期范围?

Lau*_*lbe 5

是的,您的查询在语义上是相同的,但语法也很重要。

为了得到索引的支持,WHERE条件必须如下所示:

<indexed expression> <operator> <constant>

  • <indexed expression>是用在什么CREATE INDEX

  • <operator>是索引运算符类中的运算符

  • <constant>在索引扫描期间必须保持不变(至少STABLE

此外,PostgreSQL 知道支持函数,允许它在某些其他情况下使用索引扫描,但这并不适用于此。

您的问题是运算符<@,B 树索引不支持该运算符。因此,PostgreSQL 无法使用索引来检查您的条件。因此,请继续使用您的原始查询。

为了支持<@,您需要一个 GiST 索引。