Thread: Planner forces seq scan when select without quoting its values

Planner forces seq scan when select without quoting its values

From
Alex Lai
Date:
alex1 is a table with 47 million rows and a rule that deletes from another
table whenever an insert is made into alex1.  Insertions into alex1 are
causing
a seq scan that takes a very long time:

   "EXPLAIN insert into alex1 (fileid, archiveset) select 35352974, 10003;"
     (EXPLAIN output is at the bottom of this post)

Interestingly, quoting the values causes the plannner to use an index scan,
making the operation several orders of magnitude faster:

   "EXPLAIN insert into alex1 (fileid, archiveset) select '35352974',
'10003';"
     (EXPLAIN output is at the bottom of this post)


Can someone please tell me how to write the insert statement without the
quotes, but
still executes quickly?


Some additional information:

All search columns have a b-tree index.

Relevant parameter values:
     effective_cache_size = 16GB
     cpu_operator_cost = 0.0025
     cpu_tuple_cost = 0.01
     cursor_tuple_fraction = 0.1
     enable_bitmapscan = on
     enable_hashagg = on
     enable_hashjoin = on
     enable_indexscan = on
     enable_material = on
     enable_mergejoin = on
     enable_nestloop = on
     enable_seqscan = on
     enable_sort = on
     enable_tidscan = on


This line from the EXPLAIN output suggests that the rule is causing a
seq scan
to be used instead on an index scan:

   ... WHERE ...   a.archiveset = new.archiveset AND a.fileid <> new.fileid.

When I replace the "new." with actual integers:

   ... WHERE ...   a.archiveset = 10003 AND a.fileid <>  35352974,

the problem goes away.

That makes me think that the planner is unable to find the index, so it
instead
uses a seq scan.



alex1 table:

             Table "public.alex1"
     Column |     Type     | Modifiers | Storage | Description

------------+--------------------------+-----------+---------+-------------
     fileid   | integer      |     | plain |
     archiveset | integer      |     | plain |
     lastchange | timestamp with time zone |     | plain |
     Indexes:
     "pk_alex1_archiveset" btree (archiveset)
     "pk_alex1_archiveset_lastchange" btree (archiveset, lastchange)
     "pk_alex1_fileid" btree (fileid)
     "pk_alex1_fileid_archiveset" btree (fileid, archiveset)
     "pk_alex1_lastchange" btree (lastchange)
     Rules:
     alex_rule AS
     ON INSERT TO alex1 DO  DELETE FROM alex1 fa
     WHERE ((fa.fileid, fa.archiveset) IN ( SELECT a.fileid, a.archiveset
         FROM alex1 a
     JOIN filemeta m ON m.fileid = a.fileid
     JOIN filemeta o ON o.esdt::text = m.esdt::text AND o.key::text =
m.key::text
     WHERE o.fileid = new.fileid AND a.archiveset = new.archiveset AND
a.fileid <> new.fileid))
     Has OIDs: no



filemeta table:

                 Table "public.filemeta"
     Column |   Type    | Modifiers | Storage  |         Description

--------+-------------------+-----------+----------+----------------------------------------------------------
     fileid | integer     | not null  | plain  |  The unique SIPS
generated file identifier
     esdt | character varying |     | extended |  The Earth Science Data
Type indicates the file contents
     key  | character varying |     | extended |
     source | character varying |     | extended |
     Indexes:
     "pk_filemeta" PRIMARY KEY, btree (fileid)
     "ak_filemeta_esdt" btree (esdt)
     "ak_filemeta_esdt_fileid" btree (fileid, esdt)
     "ak_filemeta_esdt_key" btree (esdt, key)
     "ak_filemeta_fileid" btree (fileid)
     "ak_filemeta_key" btree (key)
     "ak_filemeta_source" btree (source)
     Foreign-key constraints:
     "fk_filemeta_esdt" FOREIGN KEY (esdt) REFERENCES esdt_def(esdt)
DEFERRABLE
     "fk_filemeta_file" FOREIGN KEY (fileid) REFERENCES file(fileid) ON
DELETE CASCADE
     "fk_filemeta_source" FOREIGN KEY (source) REFERENCES source_def(source)
     Child tables: filemeta_anc,
         filemeta_app,
         filemeta_clg_aux,
         filemeta_l0,
         filemeta_l0r,
         filemeta_mdkey,
         filemeta_ompslookup,
         filemeta_orbital,
         filemeta_timerange
     Has OIDs: no




===== SLOW INSERT (without quotes)
==================================================================

explain insert into alex1 (fileid, archiveset) select 35352974, 10003;
                                                                  QUERY PLAN

----------------------------------------------------------------------------------------------------------------------------------------------
  Insert on alex1  (cost=0.00..0.02 rows=1 width=8)
    ->  Subquery Scan on "*SELECT*"  (cost=0.00..0.02 rows=1 width=8)
          ->  Result  (cost=0.00..0.01 rows=1 width=0)

  Delete on alex1 fa  (cost=0.00..1023312671395.36 rows=23786988 width=38)
    ->  Nested Loop  (cost=0.00..1023312671395.36 rows=23786988 width=38)
          Join Filter: (SubPlan 1)
          ->  Subquery Scan on "*SELECT*"  (cost=0.00..0.02 rows=1 width=40)
                ->  Result  (cost=0.00..0.01 rows=1 width=0)
          ->  Seq Scan on alex1 fa  (cost=0.00..732896.76 rows=47573976
width=14)
          SubPlan 1
            ->  Nested Loop  (cost=14.98..43004.15 rows=263 width=8)
                  ->  Nested Loop  (cost=14.98..12534.34 rows=13493 width=4)
                        Join Filter: (((m.esdt)::text = (o.esdt)::text)
AND ((m.key)::text = (o.key)::text))
                        ->  Append  (cost=0.00..37.68 rows=13 width=45)
                              ->  Index Scan using ak_filemeta_fileid on
filemeta o  (cost=0.00..4.29 rows=1 width=64)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using pk_filemeta_anc on
filemeta_anc o  (cost=0.00..3.28 rows=1 width=34)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Bitmap Heap Scan on filemeta_app o
(cost=1.77..4.34 rows=2 width=64)
                                    Recheck Cond: (fileid =
"*SELECT*"."?column?")
                                    ->  Bitmap Index Scan on
ak_filemeta_app_fileid  (cost=0.00..1.77 rows=2 width=0)
                                          Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Bitmap Heap Scan on filemeta_clg_aux
o  (cost=1.77..5.49 rows=3 width=64)
                                    Recheck Cond: (fileid =
"*SELECT*"."?column?")
                                    ->  Bitmap Index Scan on
ak_filemeta_clg_aux_fileid_esdt  (cost=0.00..1.77 rows=3 width=0)
                                          Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using pk_filemeta_l0 on
filemeta_l0 o  (cost=0.00..3.28 rows=1 width=30)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using pk_filemeta_l0r on
filemeta_l0r o  (cost=0.00..3.27 rows=1 width=32)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using
ak_filemeta_mdkey_fileid on filemeta_mdkey o  (cost=0.00..3.31 rows=1
width=21)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using
filemeta_ompslookup_pkey on filemeta_ompslookup o  (cost=0.00..3.27
rows=1 width=35)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using pk_filemeta_orbital
on filemeta_orbital o  (cost=0.00..3.48 rows=1 width=14)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                              ->  Index Scan using pk_filemeta_timerange
on filemeta_timerange o  (cost=0.00..3.67 rows=1 width=34)
                                    Index Cond: (fileid =
"*SELECT*"."?column?")
                        ->  Append  (cost=14.98..951.76 rows=635 width=68)
                              ->  Bitmap Heap Scan on filemeta m
(cost=14.98..922.36 rows=624 width=68)
                                    Recheck Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                                    ->  Bitmap Index Scan on
ak_filemeta_esdt_key  (cost=0.00..14.83 rows=624 width=0)
                                          Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using ak_filemeta_anc_key
on filemeta_anc m  (cost=0.00..3.30 rows=1 width=38)
                                    Index Cond: ((key)::text =
(o.key)::text)
                              ->  Index Scan using
ak_filemeta_app_esdt_key on filemeta_app m  (cost=0.00..1.31 rows=1
width=68)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using
ak_filemeta_clg_aux_fileid_esdt on filemeta_clg_aux m  (cost=0.00..5.82
rows=3 width=68)
                                    Index Cond: ((esdt)::text =
(o.esdt)::text)
                              ->  Index Scan using
ak_filemeta_l0_esdt_key on filemeta_l0 m  (cost=0.00..3.30 rows=1 width=34)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using
ak_filemeta_l0r_esdt_key on filemeta_l0r m  (cost=0.00..2.35 rows=1
width=36)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using
ak_filemeta_mdkey_esdt_key on filemeta_mdkey m  (cost=0.00..3.35 rows=1
width=25)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using
ak_filemeta_ompslookup_esdt_key on filemeta_ompslookup m
(cost=0.00..2.12 rows=1 width=39)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using
ak_filemeta_orbital_esdt_key on filemeta_orbital m  (cost=0.00..3.60
rows=1 width=18)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                              ->  Index Scan using
ak_filemeta_timerange_esdt_key on filemeta_timerange m  (cost=0.00..4.25
rows=1 width=38)
                                    Index Cond: (((esdt)::text =
(o.esdt)::text) AND ((key)::text = (o.key)::text))
                  ->  Index Scan using pk_alex1_fileid_archiveset on
alex1 a  (cost=0.00..2.25 rows=1 width=8)
                        Index Cond: ((fileid = m.fileid) AND (archiveset
= "*SELECT*"."?column?"))
                        Filter: (fileid <> "*SELECT*"."?column?")
(65 rows)
============================================================================================





===== FAST INSERT (with quotes)
============================================================

explain insert into alex1 (fileid, archiveset) select '35352974', '10003';

QUERY PLAN

--------------------------------------------------------------------------------------------------------------------------------------------------------
  Insert on alex1  (cost=0.00..0.02 rows=1 width=0)
    ->  Subquery Scan on "*SELECT*"  (cost=0.00..0.02 rows=1 width=0)
          ->  Result  (cost=0.00..0.01 rows=1 width=0)

  Delete on alex1 fa  (cost=43024.02..90401.39 rows=2664064 width=56)
    ->  Nested Loop  (cost=43024.02..90401.39 rows=2664064 width=56)
          ->  Subquery Scan on "*SELECT*"  (cost=0.00..0.02 rows=1 width=24)
                ->  Result  (cost=0.00..0.01 rows=1 width=0)
          ->  Nested Loop  (cost=43024.02..63760.73 rows=2664064 width=32)
                ->  HashAggregate  (cost=43024.02..43063.76 rows=3974
width=38)
                      ->  Nested Loop  (cost=14.98..43004.15 rows=3974
width=38)
                            ->  Nested Loop  (cost=14.98..12534.34
rows=13493 width=24)
                                  Join Filter: (((m.esdt)::text =
(o.esdt)::text) AND ((m.key)::text = (o.key)::text))
                                  ->  Append  (cost=0.00..37.68 rows=13
width=55)
                                        ->  Index Scan using
ak_filemeta_fileid on filemeta o  (cost=0.00..4.29 rows=1 width=74)
                                              Index Cond: (fileid =
35352974)
                                        ->  Index Scan using
pk_filemeta_anc on filemeta_anc o  (cost=0.00..3.28 rows=1 width=44)
                                              Index Cond: (fileid =
35352974)
                                        ->  Bitmap Heap Scan on
filemeta_app o  (cost=1.77..4.34 rows=2 width=74)
                                              Recheck Cond: (fileid =
35352974)
                                              ->  Bitmap Index Scan on
ak_filemeta_app_fileid  (cost=0.00..1.77 rows=2 width=0)
                                                    Index Cond: (fileid
= 35352974)
                                        ->  Bitmap Heap Scan on
filemeta_clg_aux o  (cost=1.77..5.49 rows=3 width=74)
                                              Recheck Cond: (fileid =
35352974)
                                              ->  Bitmap Index Scan on
ak_filemeta_clg_aux_fileid_esdt  (cost=0.00..1.77 rows=3 width=0)
                                                    Index Cond: (fileid
= 35352974)
                                        ->  Index Scan using
pk_filemeta_l0 on filemeta_l0 o  (cost=0.00..3.28 rows=1 width=40)
                                              Index Cond: (fileid =
35352974)
                                        ->  Index Scan using
pk_filemeta_l0r on filemeta_l0r o  (cost=0.00..3.27 rows=1 width=42)
                                              Index Cond: (fileid =
35352974)
                                        ->  Index Scan using
ak_filemeta_mdkey_fileid on filemeta_mdkey o  (cost=0.00..3.31 rows=1
width=31)
                                              Index Cond: (fileid =
35352974)
                                        ->  Index Scan using
filemeta_ompslookup_pkey on filemeta_ompslookup o  (cost=0.00..3.27
rows=1 width=45)
                                              Index Cond: (fileid =
35352974)
                                        ->  Index Scan using
pk_filemeta_orbital on filemeta_orbital o  (cost=0.00..3.48 rows=1 width=24)
                                              Index Cond: (fileid =
35352974)
                                        ->  Index Scan using
pk_filemeta_timerange on filemeta_timerange o  (cost=0.00..3.67 rows=1
width=44)
                                              Index Cond: (fileid =
35352974)
                                  ->  Append  (cost=14.98..951.76
rows=635 width=78)
                                        ->  Bitmap Heap Scan on filemeta
m  (cost=14.98..922.36 rows=624 width=78)
                                              Recheck Cond:
(((esdt)::text = (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                              ->  Bitmap Index Scan on
ak_filemeta_esdt_key  (cost=0.00..14.83 rows=624 width=0)
                                                    Index Cond:
(((esdt)::text = (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_anc_key on filemeta_anc m  (cost=0.00..3.30 rows=1 width=48)
                                              Index Cond: ((key)::text =
(o.key)::text)
                                        ->  Index Scan using
ak_filemeta_app_esdt_key on filemeta_app m  (cost=0.00..1.31 rows=1
width=78)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_clg_aux_fileid_esdt on filemeta_clg_aux m  (cost=0.00..5.82
rows=3 width=78)
                                              Index Cond: ((esdt)::text
= (o.esdt)::text)
                                        ->  Index Scan using
ak_filemeta_l0_esdt_key on filemeta_l0 m  (cost=0.00..3.30 rows=1 width=44)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_l0r_esdt_key on filemeta_l0r m  (cost=0.00..2.35 rows=1
width=46)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_mdkey_esdt_key on filemeta_mdkey m  (cost=0.00..3.35 rows=1
width=35)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_ompslookup_esdt_key on filemeta_ompslookup m
(cost=0.00..2.12 rows=1 width=49)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_orbital_esdt_key on filemeta_orbital m  (cost=0.00..3.60
rows=1 width=28)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                                        ->  Index Scan using
ak_filemeta_timerange_esdt_key on filemeta_timerange m  (cost=0.00..4.25
rows=1 width=48)
                                              Index Cond: (((esdt)::text
= (o.esdt)::text) AND ((key)::text = (o.key)::text))
                            ->  Index Scan using
pk_alex1_fileid_archiveset on alex1 a  (cost=0.00..2.25 rows=1 width=14)
                                  Index Cond: ((fileid = m.fileid) AND
(archiveset = 10003))
                                  Filter: (fileid <> 35352974)
                ->  Index Scan using pk_alex1_fileid_archiveset on alex1
fa  (cost=0.00..5.20 rows=1 width=14)
                      Index Cond: ((fileid = m.fileid) AND (archiveset =
10003))
(66 rows)

--
Best regards,


Alex Lai
OMI SIPS DBA ADNET Systems , Inc.
7515 Mission Drive,
Suite A100 Lanham, MD 20706
301-352-4657 (phone)
301-352-0437 (fax)
alai@sesda2.com



Re: Planner forces seq scan when select without quoting its values

From
Tom Lane
Date:
Alex Lai <mlai@sesda2.com> writes:
>    "EXPLAIN insert into alex1 (fileid, archiveset) select 35352974, 10003;"
> [vs]
>    "EXPLAIN insert into alex1 (fileid, archiveset) select '35352974', '10003';"

You might be happier using INSERT ... VALUES instead of INSERT
... SELECT for this.  In the former, the parser is going to be more
aggressive about forcing values to the correct datatype, which is the
root of your difficulties here.

            regards, tom lane


Re: Planner forces seq scan when select without quoting its values

From
Alex Lai
Date:
On 09/13/2012 09:59 AM, Tom Lane wrote:
> Alex Lai<mlai@sesda2.com>  writes:
>>     "EXPLAIN insert into alex1 (fileid, archiveset) select 35352974, 10003;"
>> [vs]
>>     "EXPLAIN insert into alex1 (fileid, archiveset) select '35352974', '10003';"
> You might be happier using INSERT ... VALUES instead of INSERT
> ... SELECT for this.  In the former, the parser is going to be more
> aggressive about forcing values to the correct datatype, which is the
> root of your difficulties here.
>
>             regards, tom lane
Tom,

I noticed using VALUES works like this query.
"insert into alex1 (fileid, archiveset) values(35352974, 10003);"
The problem I am facing is our application need to clone a number of
rows from another select statement.

I do not find a way to insert based on a select statement without
writing PG-PLSQL.  I hope to find a way like casting the datatype, but I
have not the solution.

I tried like
... WHERE ...   a.archiveset::INTEGER = new.archiveset::INTEGER AND
a.fileid::INTEGER <> new.fileid::INTEGER.
it still do the seq scan.


--
Best regards,


Alex Lai
OMI SIPS DBA ADNET Systems , Inc.
7515 Mission Drive,
Suite A100 Lanham, MD 20706
301-352-4657 (phone)
301-352-0437 (fax)
alai@sesda2.com



Re: Planner forces seq scan when select without quoting its values

From
Alex Lai
Date:
> This line from the EXPLAIN output suggests that the rule is causing a
> seq scan
> to be used instead on an index scan:
>
>   ... WHERE ...   a.archiveset = new.archiveset AND a.fileid <>
> new.fileid.
>
> When I replace the "new." with actual integers:
>
>   ... WHERE ...   a.archiveset = 10003 AND a.fileid <>  35352974,
>
> the problem goes away.
>
> That makes me think that the planner is unable to find the index, so
> it instead
> uses a seq scan.
>
I still don't have find any good suggestion.
If the cause by the key word "new" or "old" in the rule, the planner is
confused which index to use.
I think this is should be considered as a bug for rule system related to
planner.  I am not sure 9.2 will address this issue.

--
Best regards,


Alex Lai
OMI SIPS DBA ADNET Systems , Inc.
7515 Mission Drive,
Suite A100 Lanham, MD 20706
301-352-4657 (phone)
301-352-0437 (fax)
alai@sesda2.com