Re: [HACKERS] indexes and floats - Mailing list pgsql-hackers

From Tom Lane
Subject Re: [HACKERS] indexes and floats
Date
Msg-id 28284.902202647@sss.pgh.pa.us
Whole thread Raw
In response to Re: [HACKERS] indexes and floats  ("Thomas G. Lockhart" <lockhart@alumni.caltech.edu>)
Responses Re: [HACKERS] indexes and floats
List pgsql-hackers
"Thomas G. Lockhart" <lockhart@alumni.caltech.edu> writes:
>> The table consists of city, state (both text), lon and lat (both
>> float4). The text index is working but not the floats.  I have another
>> table with 12,000 - 14,000 rows and I'm getting the same thing.

> Anyway, the problem seems to be specific to float4. The workaround is to
> use float8 for now, and we'll look into fixing the problem for the next
> release...

Ah-hah, all of a sudden this looks *real* familiar.  I bet it's because
pgsql is not noticing that "500.0" can be interpreted as a float4.
Let's try it.

play=> create table f8 (x float8);
CREATE
play=> \copy f8 from countup;            // 0..999 in a text file
Successfully copied.
play=> create index f8_i on f8 using btree (x);
CREATE
play=> create table f4 (x float4);
CREATE
play=> \copy f4 from countup;
Successfully copied.
play=> create index f4_i on f4 using btree (x);
CREATE
play=> vacuum verbose analyze;
.... blah blah
play=> explain select x from f8 where x = 500;
NOTICE:  QUERY PLAN:

Seq Scan on f8  (cost=40.00 size=100 width=8)

EXPLAIN
play=> explain select x from f8 where x = 500.0;
NOTICE:  QUERY PLAN:

Index Scan using f8_i on f8  (cost=2.05 size=1 width=8)

EXPLAIN
play=> explain select x from f4 where x = 500;
NOTICE:  QUERY PLAN:

Seq Scan on f4  (cost=40.00 size=100 width=4)

EXPLAIN
play=> explain select x from f4 where x = 500.0;
NOTICE:  QUERY PLAN:

Seq Scan on f4  (cost=40.00 size=1 width=4)

EXPLAIN
play=> explain select x from f4 where x = 500 :: float4;
NOTICE:  QUERY PLAN:

Index Scan using f4_i on f4  (cost=2.05 size=1 width=4)

EXPLAIN
play=> explain select x from f4 where x = 500.0 :: float4;
ERROR:  parser_typecast: cannot cast this expression to type 'float4'
play=>

(This is with cvs sources of a few days ago.)

I see two different bugs here:

1. select ... where x = constant; is optimized to an index scan
only if the constant is of the exact type of the field x.
Apparently, the coercion of the constant to match the type of x
happens only after the optimizer decides it doesn't know what to do.
The coercion ought to happen *before* the optimizer runs.
(I have no idea whether this is a new bug caused by the recent
type-system changes, or whether it existed in 6.3.2 and earlier.)

2. Type coercion fails for "500.0 :: float4" (ditto for "500.0 :: float8"
btw).  Presumably this is a simple localized bug in the parser or the type
coercion logic for floats.

I had previously complained of bug #1 in connection with OIDs;
with the present sources, "where oid = 123456" will not use
an index on OID, while "where oid = 123456::oid" will.

I will bet lunch (at the nearest McD's, I'm not rich ;-)) that
Vince Vielhaber's recent gripe about
    select city from locations where lower(city) = lower('st. ignace');
failing to use an index
    create index locations_city on locations(lower(city) text_ops);
is an artifact of the same sort of type-mismatch problem.

            regards, tom lane

pgsql-hackers by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: [PG95-DEV] Rule system
Next
From: Tom
Date:
Subject: Re: [HACKERS] number of opened files ?