RE: [SQL] indexing a datetime by date

Started by Jackson, DeJuanalmost 27 years ago7 messages
#1Jackson, DeJuan
djackson@cpsgroup.com

Part of the problem is that PostgreSQL Assumes that a functions value will
change each time it is required, therefore automatic table scan and the
function is called for each row.
Try using 'now'::date instead of now()::date
You index creation syntax is good but there's a bug in function indexes
which require you to specify the ops. Try:
create index when_ndx3 on notes (date(when) date_ops);

Which won't work because the date(datetime) function isn't trusted.
You can change this yourself in the system tables or you can use PL/PGSQL
(the only trustable PL in PostgreSQL that I've found) to create another
conversion function and use it instead. Or you can as Thomas Lockhart (or
is it Tom Lane) if he'd create a trusted function for the conversions in
6.5.
DISCLAIMER: I haven't tested this on the current CSV(?CVS I just can't think
tonight) so it might already be fixed.
-DEJ

Show quoted text

-----Original Message-----
From: Andrew Merrill [mailto:andrew@compclass.com]
Sent: Monday, March 29, 1999 9:28 PM
To: pgsql-sql@hub.org
Subject: [SQL] indexing a datetime by date

I have a table with a field, "when", of type "datetime". I can't use
"date" because I need the times as well. I'm using PostgreSQL 6.4.2.

I'd like to identify all of the records with today's date, as in:

select when from notes where when::date = now()::date;

The query works, but is very slow. Explain confirms that a sequential
scan is being used.

I've tried indexing on when:

create index when_ndx1 on notes (when);

But that doesn't help, as (I suppose) the optimizer can't match
when::date with this index.

Neither of these works:

db=> create index when_ndx2 on notes (when::date);
ERROR: parser: parse error at or near "::"

db=> create index when_ndx3 on notes (date(when));
ERROR: DefineIndex: class not found

As a workaround, I've been using this:

select when from notes where when >= '3/29/1999 0:0:0' and when <=
'3/29/1999 23:59:59';

but that's ugly and requires hardcoding today's date each time, rather
than using now().

So, the question is, is there a way to index a datetime field by date?

Andrew Merrill

#2Thomas Lockhart
lockhart@alumni.caltech.edu
In reply to: Jackson, DeJuan (#1)
Re: [SQL] indexing a datetime by date

Your index creation syntax is good but there's a bug in function
indexes which require you to specify the ops. Try:
create index when_ndx3 on notes (date(when) date_ops);
Which won't work because the date(datetime) function isn't trusted.
You can change this yourself in the system tables or you can use
PL/PGSQL (the only trustable PL in PostgreSQL that I've found) to
create another conversion function and use it instead. Or you can as
Thomas Lockhart (or is it Tom Lane) if he'd create a trusted function
for the conversions in 6.5.

Tom, does this ring a bell with you? istm that (almost) all builtin
functions should be trusted, but I haven't done anything explicit
about it that I can remember.

In your new role as System Table Berserker, perhaps you would want to
fix this? :)

- Tom

#3Herouth Maoz
herouth@oumail.openu.ac.il
In reply to: Jackson, DeJuan (#1)

At 06:07 +0200 on 30/03/1999, Jackson, DeJuan wrote:

Part of the problem is that PostgreSQL Assumes that a functions value will
change each time it is required, therefore automatic table scan and the
function is called for each row.
Try using 'now'::date instead of now()::date

How about using the ANSI standard CURRENT_DATE instead of either? It's
already of type date. Or is it considered a function call?

Herouth

--
Herouth Maoz, Internet developer.
Open University of Israel - Telem project
http://telem.openu.ac.il/~herutma

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Herouth Maoz (#3)
Re: [SQL] indexing a datetime by date

Thomas Lockhart <lockhart@alumni.caltech.edu> writes:

create index when_ndx3 on notes (date(when) date_ops);
Which won't work because the date(datetime) function isn't trusted.

Tom, does this ring a bell with you?

No, and in fact datetime_date *is* marked trusted in pg_proc,
both current sources and 6.4.2.

I see the problem DeJuan is getting at:

play=> create table notes (when datetime);
CREATE
play=> create index when_ndx3 on notes (date(when) date_ops);
CREATE
play=> insert into notes values ('now');
ERROR: internal error: untrusted function not supported.

This is either a bug or a very poorly worded error message.
I'll look into it.

In the meantime, a workaround is to call the function using its
builtin name:

play=> create table notes (when datetime);
CREATE
play=> create index when_ndx3 on notes (datetime_date(when) date_ops);
CREATE
play=> insert into notes values ('now');
INSERT 1086489 1

In 6.4.2, date() on a datetime is an SQL-language function that just
calls the builtin function datetime_date(). It would seem that 6.4.2
can't cope with an SQL-language function as an index generator. This
might be a minor bug or it might be difficult to change; I dunno.

In 6.5, date() on a datetime is a true builtin, on par with
datetime_date(), so you'll be able to use either name interchangeably in
that release. But we may still not be able to do anything with other
SQL-language functions as index generators.

regards, tom lane

#5Andrew Merrill
andrew@compclass.com
In reply to: Tom Lane (#4)
Re: [SQL] indexing a datetime by date

Tom Lane wrote:

In the meantime, a workaround is to call the function using its
builtin name:

play=> create table notes (when datetime);
CREATE
play=> create index when_ndx3 on notes (datetime_date(when) date_ops);
CREATE

Thanks, that helps - I can now index a datetime field by date.But the index
doesn't appear to be used:

db=> create index ndx3 on notes (datetime_date(when) date_ops);
CREATE
db=> vacuum analyze notes;
VACUUM
db=> explain select when from notes where when::date = 'now'::date;
NOTICE: QUERY PLAN:

Seq Scan on notes (cost=4330.37 size=43839 width=8)

EXPLAIN

So it appears that the optimizer doesn't like this index. (This is with
version 6.4.2.)
The table has about 90,000 rows, of which between 10 and 100 might match a
given date, so an index would really help.

Am I missing something simple here? Thanks again for all your help.

Andrew Merrill

#6Jackson, DeJuan
djackson@cpsgroup.com
In reply to: Andrew Merrill (#5)

try:
explain select when from notes where datetime_date(when) = 'now'::date;
-DEJ

Show quoted text

Tom Lane wrote:

In the meantime, a workaround is to call the function using its
builtin name:

play=> create table notes (when datetime);
CREATE
play=> create index when_ndx3 on notes (datetime_date(when)

date_ops);

CREATE

Thanks, that helps - I can now index a datetime field by
date.But the index
doesn't appear to be used:

db=> create index ndx3 on notes (datetime_date(when) date_ops);
CREATE
db=> vacuum analyze notes;
VACUUM
db=> explain select when from notes where when::date = 'now'::date;
NOTICE: QUERY PLAN:

Seq Scan on notes (cost=4330.37 size=43839 width=8)

EXPLAIN

So it appears that the optimizer doesn't like this index.
(This is with
version 6.4.2.)
The table has about 90,000 rows, of which between 10 and 100
might match a
given date, so an index would really help.

Am I missing something simple here? Thanks again for all your help.

Andrew Merrill

#7Andrew Merrill
andrew@compclass.com
In reply to: Jackson, DeJuan (#6)
Re: [SQL] indexing a datetime by date

Jackson, DeJuan wrote:

try:
explain select when from notes where datetime_date(when) = 'now'::date;
-DEJ

Aha. That does the trick. Thanks!

Andrew Merrill