Slow query to get last created row using CURRVAL

From: Mathieu De Zutter <mathieu(at)dezutter(dot)org>
To: pgsql-performance(at)postgresql(dot)org
Subject: Slow query to get last created row using CURRVAL
Date: 2010-12-04 11:56:50
Message-ID: AANLkTik7Oz9UHf9WjJuoxZgJxZwqoooCkyZP_KHf=Z-5@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-performance

Hi all,

I have a table that stores all the page loads in my web application:

shs-dev=# \d log_event
Table "public.log_event"
Column | Type |
Modifiers
-----------------+--------------------------+--------------------------------------------------------
id | bigint | not null default
nextval('log_event_id_seq'::regclass)
user_id | integer |
ip | inet | not null
action_id | integer | not null
object1_id | integer |
object2_id | integer |
event_timestamp | timestamp with time zone | not null
data | text |
comments | text |
Indexes:
"log_event_pkey" PRIMARY KEY, btree (id)
"log_event_action_id_idx" btree (action_id)
"log_event_object1_idx" btree (object1_id)
"log_event_object2_idx" btree (object2_id)
"log_event_timestamp_idx" btree (event_timestamp)
"log_event_user_id_idx" btree (user_id)
Foreign-key constraints:
"log_event_action_id_fkey" FOREIGN KEY (action_id) REFERENCES
config.log_action(id)
Referenced by:
TABLE "log_data" CONSTRAINT "log_data_event_id_fkey" FOREIGN KEY
(event_id) REFERENCES log_event(id) ON DELETE CASCADE DEFERRABLE
INITIALLY DEFERRED
TABLE "log_report" CONSTRAINT "log_report_event_id_fkey" FOREIGN
KEY (event_id) REFERENCES log_event(id)

shs-dev=# select count(*) from log_event;
count
---------
5755566

For each page load I first create an entry in that table, e.g.:

INSERT INTO log_event (user_id, ip, action_id, object1_id, object2_id,
event_timestamp, comments) VALUES (1, '127.0.0.1', 96, null, null,
NOW(), 'TEST');

After that, I want to retrieve the data stored in log_event from a
trigger, e.g.:

SELECT user_id FROM log_event WHERE id = CURRVAL('log_event_id_seq');

This way my insert-trigger knows who is creating the new row, while
using only one pg-user to query the database.

The problem is that this query is very slow because it refuses to use
an index scan:

shs-dev=# set enable_seqscan = off;
SET
shs-dev=# explain analyze SELECT user_id FROM log_event WHERE id =
CURRVAL('log_event_id_seq');
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Seq Scan on log_event (cost=10000000000.00..10000139202.07 rows=1
width=4) (actual time=2086.272..2086.273 rows=1 loops=1)
Filter: (id = currval('log_event_id_seq'::regclass))
Total runtime: 2086.305 ms

If I specify one specific value, it's OK:

shs-dev=# explain analyze SELECT user_id FROM log_event WHERE id =
1283470192837401;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Index Scan using log_event_pkey on log_event (cost=0.00..8.90 rows=1
width=4) (actual time=0.034..0.034 rows=0 loops=1)
Index Cond: (id = 1283470192837401::bigint)
Total runtime: 0.056 ms

If I experiment with RANDOM, it's slow again:

shs-dev=# explain analyze SELECT user_id FROM log_event WHERE id =
RANDOM()::bigint;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Seq Scan on log_event (cost=10000000000.00..10000153591.24 rows=1
width=4) (actual time=1353.425..1353.425 rows=0 loops=1)
Filter: (id = (random())::bigint)
Total runtime: 1353.452 ms

On the other hand, for some undeterministic cases, it does run fast:
(in this example the planner cannot predict what will be the value of
the filter condition)

shs-dev=# explain analyze SELECT user_id FROM log_event WHERE id =
(select id from artist where id > 1000 limit 1);
QUERY
PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Index Scan using log_event_pkey on log_event (cost=0.08..8.98 rows=1
width=4) (actual time=0.069..0.069 rows=0 loops=1)
Index Cond: (id = $0)
InitPlan 1 (returns $0)
-> Limit (cost=0.00..0.08 rows=1 width=4) (actual
time=0.039..0.039 rows=1 loops=1)
-> Index Scan using artist_pkey on artist
(cost=0.00..3117.11 rows=40252 width=4) (actual time=0.038..0.038
rows=1 loops=1)
Index Cond: (id > 1000)

I have no idea why in some cases the index scan is not considered.
Does anyone have an idea?

Thanks!

Kind regards,
Mathieu

Responses

Browse pgsql-performance by date

  From Date Subject
Next Message Marti Raudsepp 2010-12-04 12:35:33 Re: Slow query to get last created row using CURRVAL
Previous Message Markus Schulz 2010-12-04 10:24:02 Re: problem with from_collapse_limit and joined views