Обсуждение: Daterange question

Поиск
Список
Период
Сортировка

Daterange question

От
Andreas Joseph Krogh
Дата:

I have order-lines with start-end like this:

start_date  DATE      NOT NULL,
end_date    DATE,
drange      daterange NOT NULL GENERATED ALWAYS AS (daterange(start_date, end_date, '[)')) STORED

and have an index on using gist(drange)

 

I want to list all order-lines which does not have end-date set in the past, but want to show lines with start-dates in future.

 

This seems to do what I want:

NOT (drange << daterange(CURRENT_DATE, NULL, '[)'))

But this doesn't use the index.

 

Any idea how to write a query so it uses the index on drange?

 

Thanks.

 

--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963
Вложения

Re: Daterange question

От
Adrian Klaver
Дата:
On 1/19/24 20:08, Andreas Joseph Krogh wrote:
> I have order-lines with start-end like this:
> 
> |start_date DATE NOT NULL, end_date DATE, drange daterange NOT NULL 
> GENERATED ALWAYS AS (daterange(start_date, end_date, '[)')) STORED|
> 
> and have an index on |using gist(drange)|
> 
> I want to list all order-lines which does not have end-date set in the 
> past, but want to show lines with start-dates in future.
> 
> This seems to do what I want:
> 
> |NOT (drange << daterange(CURRENT_DATE, NULL, '[)'))|
> 
> But this doesn't use the index.
> 
> Any idea how to write a query so it uses the index on |drange|?

Without the full query and the EXPLAIN output I don't see that there is 
much that can be offered in way of an answer.

> 
> Thanks.
> 
> --
> *Andreas Joseph Krogh*
> CTO / Partner - Visena AS
> Mobile: +47 909 56 963
> andreas@visena.com <mailto:andreas@visena.com>
> www.visena.com <https://www.visena.com>
> <https://www.visena.com>

-- 
Adrian Klaver
adrian.klaver@aklaver.com




Re: Daterange question

От
Andreas Joseph Krogh
Дата:
create table order_line
(    id         serial primary key,    start_date DATE      NOT NULL,    end_date   DATE,    drange     daterange NOT NULL GENERATED ALWAYS AS (daterange(start_date, end_date, '[)')) STORED
);
CREATE INDEX order_line_not_end_idx ON order_line using gist(drange);

INSERT INTO order_line(start_date, end_date) values('2023-01-01', null);
INSERT INTO order_line(start_date, end_date) values('2023-01-01', '2024-01-01');
INSERT INTO order_line(start_date, end_date) values('2024-01-01', null);
INSERT INTO order_line(start_date, end_date) values('2025-01-01', null);

set enable_seqscan to false;

explain analyse select * from order_line WHERE (drange << daterange(CURRENT_DATE, NULL, '[)')); -- Uses index
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                             QUERY PLAN                                                             │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Index Scan using order_line_not_end_idx on order_line  (cost=0.14..8.15 rows=1 width=44) (actual time=0.008..0.008 rows=1 loops=1) │
│   Index Cond: (drange << daterange(CURRENT_DATE, NULL::date, '[)'::text))                                                          │
│ Planning Time: 0.043 ms                                                                                                            │
│ Execution Time: 0.013 ms                                                                                                           │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

explain analyse select * from order_line WHERE NOT (drange << daterange(CURRENT_DATE, NULL, '[)')); -- Does not use index
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                       QUERY PLAN                                                        │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Seq Scan on order_line  (cost=10000000000.00..10000000001.07 rows=3 width=44) (actual time=0.007..0.008 rows=3 loops=1) │
│   Filter: (NOT (drange << daterange(CURRENT_DATE, NULL::date, '[)'::text)))                                             │
│   Rows Removed by Filter: 1                                                                                             │
│ Planning Time: 0.077 ms                                                                                                 │
│ Execution Time: 0.015 ms                                                                                                │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

 

--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963
 
Вложения

Re: Daterange question

От
Tom Lane
Дата:
Adrian Klaver <adrian.klaver@aklaver.com> writes:
> On 1/19/24 20:08, Andreas Joseph Krogh wrote:
>> This seems to do what I want:
>> |NOT (drange << daterange(CURRENT_DATE, NULL, '[)'))|
>> But this doesn't use the index.
>> Any idea how to write a query so it uses the index on |drange|?

> Without the full query and the EXPLAIN output I don't see that there is 
> much that can be offered in way of an answer.

Well, we can definitively state that the NOT makes this unindexable.
You need a WHERE clause that looks like
    indexed-column indexable-operator pseudo-constant
which this isn't, nor does << have a negator operator that could
allow the NOT to be simplified out.

Wouldn't
    drange && daterange(CURRENT_DATE, NULL, '[)')
serve the purpose?  That should be indexable.

            regards, tom lane



Re: Daterange question

От
Andreas Joseph Krogh
Дата:
På lørdag 20. januar 2024 kl. 06:35:07, skrev Tom Lane <tgl@sss.pgh.pa.us>:
[…]
Well, we can definitively state that the NOT makes this unindexable.
You need a WHERE clause that looks like
indexed-column indexable-operator pseudo-constant
which this isn't, nor does << have a negator operator that could
allow the NOT to be simplified out.

Wouldn't
drange && daterange(CURRENT_DATE, NULL, '[)')
serve the purpose?  That should be indexable.

regards, tom lane

Yes it will, thanks.

 

--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963
 
Вложения