Обсуждение: Oracle v. Postgres 9.0 query performance
We are thiiiiiis close to moving our datawarehouse from Oracle to
Postgres. This query is identical on both systems, but runs much, much
faster on Oracle. Our Postgres host has far superior hardware and
tuning parameters have been set via pgtune. Most everything else runs
faster in Postgres, except for this query. In Oracle, we get a hash
join that takes about 2 minutes:
SQL> set line 200
delete from plan_table;
explain plan for
CREATE TABLE ecr_opens
as
select o.emailcampaignid, count(memberid) opencnt
from openactivity o,ecr_sents s
where s.emailcampaignid = o.emailcampaignid
group by o.emailcampaignid;
SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());
SQL>
13 rows deleted.
SQL> 2 3 4 5 6 7
Explained.
SQL> SQL>
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4034426201
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows |
Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | CREATE TABLE STATEMENT | | 5094 |
91692 | 9651 (24)| 00:02:16 | | | |
| 1 | LOAD AS SELECT | ECR_OPENS | |
| | | | | |
| 2 | PX COORDINATOR | | |
| | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10002 | 5094 |
91692 | 2263 (100)| 00:00:32 | Q1,02 | P->S | QC (RAND) |
| 4 | HASH GROUP BY | | 5094 |
91692 | 2263 (100)| 00:00:32 | Q1,02 | PCWP | |
| 5 | PX RECEIVE | | 5094 |
91692 | 2263 (100)| 00:00:32 | Q1,02 | PCWP | |
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 6 | PX SEND HASH | :TQ10001 | 5094 |
91692 | 2263 (100)| 00:00:32 | Q1,01 | P->P | HASH |
| 7 | HASH GROUP BY | | 5094 |
91692 | 2263 (100)| 00:00:32 | Q1,01 | PCWP | |
| 8 | NESTED LOOPS | | 17M|
297M| 200 (98)| 00:00:03 | Q1,01 | PCWP | |
| 9 | BUFFER SORT | | |
| | | Q1,01 | PCWC | |
| 10 | PX RECEIVE | | |
| | | Q1,01 | PCWP | |
| 11 | PX SEND ROUND-ROBIN| :TQ10000 | |
| | | | S->P | RND-ROBIN |
| 12 | TABLE ACCESS FULL | ECR_SENTS | 476 |
6188 | 3 (0)| 00:00:01 | | | |
|* 13 | INDEX RANGE SCAN | OPENACT_EMCAMP_IDX | 36355 |
177K| 1 (0)| 00:00:01 | Q1,01 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------
13 - access("S"."EMAILCAMPAIGNID"="O"."EMAILCAMPAIGNID")
Note
-----
- dynamic sampling used for this statement
29 rows selected.
SQL> desc openactivity
Name Null? Type
----------------------------------------- --------
----------------------------
EMAILCAMPAIGNID NOT NULL NUMBER
MEMBERID NOT NULL NUMBER
OPENDATE DATE
IPADDRESS VARCHAR2(25)
DATE_ID NUMBER
SQL> select count(*) from openactivity;
COUNT(*)
----------
192542480
SQL> desc ecr_sents
Name Null? Type
----------------------------------------- --------
----------------------------
EMAILCAMPAIGNID NUMBER
MEMCNT NUMBER
DATE_ID NUMBER
SENTDATE DATE
SQL> select count(*) from ecr_sents;
COUNT(*)
----------
476
Our final result is the ecr_opens table which is 476 rows.
On Postgres, this same query takes about 58 minutes (could not run
explain analyze because it is in progress):
pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
pg_dw-# as
pg_dw-# select o.emailcampaignid, count(memberid) opencnt
pg_dw-# from openactivity o,ecr_sents s
pg_dw-# where s.emailcampaignid = o.emailcampaignid
pg_dw-# group by o.emailcampaignid;
QUERY
PLAN
-------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12)
-> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12)
-> Index Scan using ecr_sents_ecid_idx on ecr_sents s
(cost=0.00..38.59 rows=479 width=4)
-> Index Scan using openact_emcamp_idx on openactivity o
(cost=0.00..3395.49 rows=19372 width=12)
Index Cond: (o.emailcampaignid = s.emailcampaignid)
(5 rows)
pg_dw=# \d openactivity
Table "openactivity"
Column | Type | Modifiers
-----------------+-----------------------+-----------
emailcampaignid | integer | not null
memberid | bigint | not null
opendate | date |
ipaddress | character varying(25) |
date_id | integer |
Indexes:
"openact_dateid_idx" btree (date_id), tablespace "pg_idx"
"openact_emcamp_idx" btree (emailcampaignid), tablespace "pg_idx"
pg_dw=# select count(*) from openactivity;
count
-----------
192542480
pg_dw=# \d ecr_sents
Table "staging.ecr_sents"
Column | Type | Modifiers
-----------------+---------+-----------
emailcampaignid | integer |
memcnt | numeric |
date_id | integer |
sentdate | date |
Indexes:
"ecr_sents_ecid_idx" btree (emailcampaignid), tablespace
"staging_idx"
pg_dw=# select count(*) from ecr_sents;
count
-------
479
We added an index on ecr_sents to see if that improved performance, but
did not work. Both tables have updated stats:
pg_dw=# select relname, last_vacuum, last_autovacuum, last_analyze,
last_autoanalyze from pg_stat_all_tables where relname in
('openactivity','ecr_sents');
relname | last_vacuum | last_autovacuum |
last_analyze | last_autoanalyze
--------------+-------------------------------+-----------------+-------------------------------+-------------------------------
ecr_sents | | |
2011-06-08 10:31:20.677172-04 | 2011-06-08 10:31:34.545504-04
openactivity | 2011-06-02 16:34:47.129695-04 | |
2011-06-07 13:48:21.909546-04 | 2011-04-27 17:49:15.004551-04
Relevant info:
pg_dw=# SELECT
pg_dw-# 'version'::text AS "name",
pg_dw-# version() AS "current_setting"
pg_dw-# UNION ALL
pg_dw-# SELECT
pg_dw-# name,current_setting(name)
pg_dw-# FROM pg_settings
pg_dw-# WHERE NOT source='default' AND NOT name IN
pg_dw-# ('config_file','data_directory','hba_file','ident_file',
pg_dw(# 'log_timezone','DateStyle','lc_messages','lc_monetary',
pg_dw(# 'lc_numeric','lc_time','timezone_abbreviations',
pg_dw(# 'default_text_search_config','application_name',
pg_dw(# 'transaction_deferrable','transaction_isolation',
pg_dw(# 'transaction_read_only');
name |
current_setting
------------------------------+-------------------------------------------------------------------------------------------------------------------
version | PostgreSQL 9.0.3 on
x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20080704 (Red
Hat 4.1.2-48), 64-bit
archive_command | (disabled)
archive_timeout | 1h
autovacuum_max_workers | 10
checkpoint_completion_target | 0.9
checkpoint_segments | 64
checkpoint_timeout | 1h
constraint_exclusion | on
default_statistics_target | 100
effective_cache_size | 22GB
effective_io_concurrency | 5
fsync | on
lc_collate | en_US.UTF-8
lc_ctype | en_US.UTF-8
listen_addresses | *
log_checkpoints | on
log_destination | stderr
log_directory | pg_log
log_error_verbosity | default
log_filename | pg_dw.log
log_line_prefix | %m-%u-%p
log_lock_waits | on
log_min_error_statement | panic
log_min_messages | notice
log_rotation_age | 0
log_rotation_size | 0
log_truncate_on_rotation | off
logging_collector | on
maintenance_work_mem | 1GB
max_connections | 400
max_stack_depth | 2MB
search_path | xxxxx
server_encoding | UTF8
shared_buffers | 7680MB
TimeZone | US/Eastern
wal_buffers | 32MB
wal_level | archive
work_mem | 768MB
Should this query be hashing the smaller table on Postgres rather than
using nested loops?
Thanks.
Tony
> On Postgres, this same query takes about 58 minutes (could not run > explain analyze because it is in progress): > > pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100) > pg_dw-# as > pg_dw-# select o.emailcampaignid, count(memberid) opencnt > pg_dw-# from openactivity o,ecr_sents s > pg_dw-# where s.emailcampaignid = o.emailcampaignid > pg_dw-# group by o.emailcampaignid; > QUERY > PLAN > ------------------------------------------------------------------------------------------------------------- > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s > (cost=0.00..38.59 rows=479 width=4) > -> Index Scan using openact_emcamp_idx on openactivity o > (cost=0.00..3395.49 rows=19372 width=12) > Index Cond: (o.emailcampaignid = s.emailcampaignid) > (5 rows) > Please, post EXPLAIN ANALYZE, not just EXPLAIN. Preferably using explain.depesz.com. regards Tomas
Tony Capobianco <tcapobianco@prospectiv.com> writes:
> pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
> pg_dw-# as
> pg_dw-# select o.emailcampaignid, count(memberid) opencnt
> pg_dw-# from openactivity o,ecr_sents s
> pg_dw-# where s.emailcampaignid = o.emailcampaignid
> pg_dw-# group by o.emailcampaignid;
> QUERY
> PLAN
> -------------------------------------------------------------------------------------------------------------
> GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12)
> -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12)
> -> Index Scan using ecr_sents_ecid_idx on ecr_sents s
> (cost=0.00..38.59 rows=479 width=4)
> -> Index Scan using openact_emcamp_idx on openactivity o
> (cost=0.00..3395.49 rows=19372 width=12)
> Index Cond: (o.emailcampaignid = s.emailcampaignid)
> (5 rows)
> Should this query be hashing the smaller table on Postgres rather than
> using nested loops?
Yeah, seems like it. Just for testing purposes, do "set enable_nestloop
= 0" and see what plan you get then.
regards, tom lane
pg_dw=# set enable_nestloop =0;
SET
Time: 0.165 ms
pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
pg_dw-# as
pg_dw-# select o.emailcampaignid, count(memberid) opencnt
pg_dw-# from openactivity o,ecr_sents s
pg_dw-# where s.emailcampaignid = o.emailcampaignid
pg_dw-# group by o.emailcampaignid;
QUERY
PLAN
-----------------------------------------------------------------------------------------
HashAggregate (cost=4391163.81..4391288.05 rows=9939 width=12)
-> Hash Join (cost=14.78..4344767.23 rows=9279316 width=12)
Hash Cond: (o.emailcampaignid = s.emailcampaignid)
-> Seq Scan on openactivity o (cost=0.00..3529930.67
rows=192540967 width=12)
-> Hash (cost=8.79..8.79 rows=479 width=4)
-> Seq Scan on ecr_sents s (cost=0.00..8.79 rows=479
width=4)
Yikes. Two sequential scans.
On Wed, 2011-06-08 at 11:33 -0400, Tom Lane wrote:
> Tony Capobianco <tcapobianco@prospectiv.com> writes:
> > pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
> > pg_dw-# as
> > pg_dw-# select o.emailcampaignid, count(memberid) opencnt
> > pg_dw-# from openactivity o,ecr_sents s
> > pg_dw-# where s.emailcampaignid = o.emailcampaignid
> > pg_dw-# group by o.emailcampaignid;
> > QUERY
> > PLAN
> > -------------------------------------------------------------------------------------------------------------
> > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12)
> > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12)
> > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s
> > (cost=0.00..38.59 rows=479 width=4)
> > -> Index Scan using openact_emcamp_idx on openactivity o
> > (cost=0.00..3395.49 rows=19372 width=12)
> > Index Cond: (o.emailcampaignid = s.emailcampaignid)
> > (5 rows)
>
> > Should this query be hashing the smaller table on Postgres rather than
> > using nested loops?
>
> Yeah, seems like it. Just for testing purposes, do "set enable_nestloop
> = 0" and see what plan you get then.
>
> regards, tom lane
>
* Tony Capobianco (tcapobianco@prospectiv.com) wrote:
> HashAggregate (cost=4391163.81..4391288.05 rows=9939 width=12)
> -> Hash Join (cost=14.78..4344767.23 rows=9279316 width=12)
> Hash Cond: (o.emailcampaignid = s.emailcampaignid)
> -> Seq Scan on openactivity o (cost=0.00..3529930.67
> rows=192540967 width=12)
> -> Hash (cost=8.79..8.79 rows=479 width=4)
> -> Seq Scan on ecr_sents s (cost=0.00..8.79 rows=479
> width=4)
>
> Yikes. Two sequential scans.
Err, isn't that more-or-less exactly what you want here? The smaller
table is going to be hashed and then you'll traverse the bigger table
and bounce each row off the hash table. Have you tried actually running
this and seeing how long it takes? The bigger table doesn't look to be
*that* big, if your i/o subsystem is decent and you've got a lot of
memory available for kernel cacheing, should be quick.
Thanks,
Stephen
Вложения
08.06.11 18:40, Tony Capobianco написав(ла):
> pg_dw=# set enable_nestloop =0;
> SET
> Time: 0.165 ms
> pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
> pg_dw-# as
> pg_dw-# select o.emailcampaignid, count(memberid) opencnt
> pg_dw-# from openactivity o,ecr_sents s
> pg_dw-# where s.emailcampaignid = o.emailcampaignid
> pg_dw-# group by o.emailcampaignid;
> QUERY
> PLAN
> -----------------------------------------------------------------------------------------
> HashAggregate (cost=4391163.81..4391288.05 rows=9939 width=12)
> -> Hash Join (cost=14.78..4344767.23 rows=9279316 width=12)
> Hash Cond: (o.emailcampaignid = s.emailcampaignid)
> -> Seq Scan on openactivity o (cost=0.00..3529930.67
> rows=192540967 width=12)
> -> Hash (cost=8.79..8.79 rows=479 width=4)
> -> Seq Scan on ecr_sents s (cost=0.00..8.79 rows=479
> width=4)
>
> Yikes. Two sequential scans.
Yep. Can you see another options? Either you take each of 479 records
and try to find matching records in another table using index (first
plan), or you take both two tables fully (seq scan) and join - second plan.
First plan is better if your large table is clustered enough on
emailcampaignid field (479 index reads and 479 sequential table reads).
If it's not, you may get a 479 table reads transformed into a lot or
random reads.
BTW: May be you have different data clustering in PostgreSQL & Oracle?
Or data in Oracle may be "hot" in caches?
Also, sequential scan is not too bad thing. It may be cheap enough to
read millions of records if they are not too wide. Please show "select
pg_size_pretty(pg_relation_size('openactivity'));" Have you tried to
explain analyze second plan?
Best regards, Vitalii Tymchyshyn
>
> On Wed, 2011-06-08 at 11:33 -0400, Tom Lane wrote:
>> Tony Capobianco<tcapobianco@prospectiv.com> writes:
>>> pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
>>> pg_dw-# as
>>> pg_dw-# select o.emailcampaignid, count(memberid) opencnt
>>> pg_dw-# from openactivity o,ecr_sents s
>>> pg_dw-# where s.emailcampaignid = o.emailcampaignid
>>> pg_dw-# group by o.emailcampaignid;
>>> QUERY
>>> PLAN
>>> -------------------------------------------------------------------------------------------------------------
>>> GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12)
>>> -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12)
>>> -> Index Scan using ecr_sents_ecid_idx on ecr_sents s
>>> (cost=0.00..38.59 rows=479 width=4)
>>> -> Index Scan using openact_emcamp_idx on openactivity o
>>> (cost=0.00..3395.49 rows=19372 width=12)
>>> Index Cond: (o.emailcampaignid = s.emailcampaignid)
>>> (5 rows)
>>> Should this query be hashing the smaller table on Postgres rather than
>>> using nested loops?
>> Yeah, seems like it. Just for testing purposes, do "set enable_nestloop
>> = 0" and see what plan you get then.
Here's the explain analyze:
pg_dw=# explain analyze CREATE TABLE ecr_opens with (FILLFACTOR=100)
as
select o.emailcampaignid, count(memberid) opencnt
from openactivity o,ecr_sents s
where s.emailcampaignid = o.emailcampaignid
group by o.emailcampaignid;
QUERY
PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) (actual
time=308630.967..2592279.526 rows=472 loops=1)
-> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12)
(actual time=31.489..2589363.047 rows=8586466 loops=1)
-> Index Scan using ecr_sents_ecid_idx on ecr_sents s
(cost=0.00..38.59 rows=479 width=4) (actual time=0.010..13.326 rows=479
loops=1)
-> Index Scan using openact_emcamp_idx on openactivity o
(cost=0.00..3395.49 rows=19372 width=12) (actual time=1.336..5397.139
rows=17926 loops=479)
Index Cond: (o.emailcampaignid = s.emailcampaignid)
Total runtime: 2592284.336 ms
On Wed, 2011-06-08 at 17:31 +0200, tv@fuzzy.cz wrote:
> > On Postgres, this same query takes about 58 minutes (could not run
> > explain analyze because it is in progress):
> >
> > pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100)
> > pg_dw-# as
> > pg_dw-# select o.emailcampaignid, count(memberid) opencnt
> > pg_dw-# from openactivity o,ecr_sents s
> > pg_dw-# where s.emailcampaignid = o.emailcampaignid
> > pg_dw-# group by o.emailcampaignid;
> > QUERY
> > PLAN
> > -------------------------------------------------------------------------------------------------------------
> > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12)
> > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12)
> > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s
> > (cost=0.00..38.59 rows=479 width=4)
> > -> Index Scan using openact_emcamp_idx on openactivity o
> > (cost=0.00..3395.49 rows=19372 width=12)
> > Index Cond: (o.emailcampaignid = s.emailcampaignid)
> > (5 rows)
> >
>
> Please, post EXPLAIN ANALYZE, not just EXPLAIN. Preferably using
> explain.depesz.com.
>
> regards
> Tomas
>
>
Hello what is your settings for random_page_cost, seq_page_cost and work_mem? Regards Pavel Stehule 2011/6/8 Tony Capobianco <tcapobianco@prospectiv.com>: > Here's the explain analyze: > > pg_dw=# explain analyze CREATE TABLE ecr_opens with (FILLFACTOR=100) > as > select o.emailcampaignid, count(memberid) opencnt > from openactivity o,ecr_sents s > where s.emailcampaignid = o.emailcampaignid > group by o.emailcampaignid; > > QUERY > PLAN > ---------------------------------------------------------------------------------------------------------------------------------------------------------------- > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) (actual > time=308630.967..2592279.526 rows=472 loops=1) > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) > (actual time=31.489..2589363.047 rows=8586466 loops=1) > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s > (cost=0.00..38.59 rows=479 width=4) (actual time=0.010..13.326 rows=479 > loops=1) > -> Index Scan using openact_emcamp_idx on openactivity o > (cost=0.00..3395.49 rows=19372 width=12) (actual time=1.336..5397.139 > rows=17926 loops=479) > Index Cond: (o.emailcampaignid = s.emailcampaignid) > Total runtime: 2592284.336 ms > > > On Wed, 2011-06-08 at 17:31 +0200, tv@fuzzy.cz wrote: >> > On Postgres, this same query takes about 58 minutes (could not run >> > explain analyze because it is in progress): >> > >> > pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100) >> > pg_dw-# as >> > pg_dw-# select o.emailcampaignid, count(memberid) opencnt >> > pg_dw-# from openactivity o,ecr_sents s >> > pg_dw-# where s.emailcampaignid = o.emailcampaignid >> > pg_dw-# group by o.emailcampaignid; >> > QUERY >> > PLAN >> > ------------------------------------------------------------------------------------------------------------- >> > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) >> > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) >> > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s >> > (cost=0.00..38.59 rows=479 width=4) >> > -> Index Scan using openact_emcamp_idx on openactivity o >> > (cost=0.00..3395.49 rows=19372 width=12) >> > Index Cond: (o.emailcampaignid = s.emailcampaignid) >> > (5 rows) >> > >> >> Please, post EXPLAIN ANALYZE, not just EXPLAIN. Preferably using >> explain.depesz.com. >> >> regards >> Tomas >> >> > > > > -- > Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) > To make changes to your subscription: > http://www.postgresql.org/mailpref/pgsql-performance >
Well, this ran much better. However, I'm not sure if it's because of
set enable_nestloop = 0, or because I'm executing the query twice in a
row, where previous results may be cached. I will try this setting in
my code for when this process runs later today and see what the result
is.
Thanks!
pg_dw=# explain analyze CREATE TABLE ecr_opens with (FILLFACTOR=100)
pg_dw-# as
pg_dw-# select o.emailcampaignid, count(memberid) opencnt
pg_dw-# from openactivity o,ecr_sents s
pg_dw-# where s.emailcampaignid = o.emailcampaignid
pg_dw-# group by o.emailcampaignid;
QUERY
PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=4391163.81..4391288.05 rows=9939 width=12) (actual
time=167254.751..167254.937 rows=472 loops=1)
-> Hash Join (cost=14.78..4344767.23 rows=9279316 width=12) (actual
time=0.300..164577.131 rows=8586466 loops=1)
Hash Cond: (o.emailcampaignid = s.emailcampaignid)
-> Seq Scan on openactivity o (cost=0.00..3529930.67
rows=192540967 width=12) (actual time=0.011..124351.878 rows=192542480
loops=1)
-> Hash (cost=8.79..8.79 rows=479 width=4) (actual
time=0.253..0.253 rows=479 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 17kB
-> Seq Scan on ecr_sents s (cost=0.00..8.79 rows=479
width=4) (actual time=0.010..0.121 rows=479 loops=1)
Total runtime: 167279.950 ms
On Wed, 2011-06-08 at 11:51 -0400, Stephen Frost wrote:
> * Tony Capobianco (tcapobianco@prospectiv.com) wrote:
> > HashAggregate (cost=4391163.81..4391288.05 rows=9939 width=12)
> > -> Hash Join (cost=14.78..4344767.23 rows=9279316 width=12)
> > Hash Cond: (o.emailcampaignid = s.emailcampaignid)
> > -> Seq Scan on openactivity o (cost=0.00..3529930.67
> > rows=192540967 width=12)
> > -> Hash (cost=8.79..8.79 rows=479 width=4)
> > -> Seq Scan on ecr_sents s (cost=0.00..8.79 rows=479
> > width=4)
> >
> > Yikes. Two sequential scans.
>
> Err, isn't that more-or-less exactly what you want here? The smaller
> table is going to be hashed and then you'll traverse the bigger table
> and bounce each row off the hash table. Have you tried actually running
> this and seeing how long it takes? The bigger table doesn't look to be
> *that* big, if your i/o subsystem is decent and you've got a lot of
> memory available for kernel cacheing, should be quick.
>
> Thanks,
>
> Stephen
pg_dw=# show random_page_cost ; random_page_cost ------------------ 4 (1 row) Time: 0.299 ms pg_dw=# show seq_page_cost ; seq_page_cost --------------- 1 (1 row) Time: 0.250 ms pg_dw=# show work_mem ; work_mem ---------- 768MB (1 row) On Wed, 2011-06-08 at 18:27 +0200, Pavel Stehule wrote: > Hello > > what is your settings for > > random_page_cost, seq_page_cost and work_mem? > > Regards > > Pavel Stehule > > 2011/6/8 Tony Capobianco <tcapobianco@prospectiv.com>: > > Here's the explain analyze: > > > > pg_dw=# explain analyze CREATE TABLE ecr_opens with (FILLFACTOR=100) > > as > > select o.emailcampaignid, count(memberid) opencnt > > from openactivity o,ecr_sents s > > where s.emailcampaignid = o.emailcampaignid > > group by o.emailcampaignid; > > > > QUERY > > PLAN > > ---------------------------------------------------------------------------------------------------------------------------------------------------------------- > > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) (actual > > time=308630.967..2592279.526 rows=472 loops=1) > > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) > > (actual time=31.489..2589363.047 rows=8586466 loops=1) > > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s > > (cost=0.00..38.59 rows=479 width=4) (actual time=0.010..13.326 rows=479 > > loops=1) > > -> Index Scan using openact_emcamp_idx on openactivity o > > (cost=0.00..3395.49 rows=19372 width=12) (actual time=1.336..5397.139 > > rows=17926 loops=479) > > Index Cond: (o.emailcampaignid = s.emailcampaignid) > > Total runtime: 2592284.336 ms > > > > > > On Wed, 2011-06-08 at 17:31 +0200, tv@fuzzy.cz wrote: > >> > On Postgres, this same query takes about 58 minutes (could not run > >> > explain analyze because it is in progress): > >> > > >> > pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100) > >> > pg_dw-# as > >> > pg_dw-# select o.emailcampaignid, count(memberid) opencnt > >> > pg_dw-# from openactivity o,ecr_sents s > >> > pg_dw-# where s.emailcampaignid = o.emailcampaignid > >> > pg_dw-# group by o.emailcampaignid; > >> > QUERY > >> > PLAN > >> > ------------------------------------------------------------------------------------------------------------- > >> > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) > >> > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) > >> > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s > >> > (cost=0.00..38.59 rows=479 width=4) > >> > -> Index Scan using openact_emcamp_idx on openactivity o > >> > (cost=0.00..3395.49 rows=19372 width=12) > >> > Index Cond: (o.emailcampaignid = s.emailcampaignid) > >> > (5 rows) > >> > > >> > >> Please, post EXPLAIN ANALYZE, not just EXPLAIN. Preferably using > >> explain.depesz.com. > >> > >> regards > >> Tomas > >> > >> > > > > > > > > -- > > Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) > > To make changes to your subscription: > > http://www.postgresql.org/mailpref/pgsql-performance > > >
Tony Capobianco <tcapobianco@prospectiv.com> writes:
> Well, this ran much better. However, I'm not sure if it's because of
> set enable_nestloop = 0, or because I'm executing the query twice in a
> row, where previous results may be cached. I will try this setting in
> my code for when this process runs later today and see what the result
> is.
If the performance differential holds up, you should look at adjusting
your cost parameters so that the planner isn't so wrong about which one
is faster. Hacking enable_nestloop is a band-aid, not something you
want to use in production.
Looking at the values you gave earlier, I wonder whether the
effective_cache_size setting isn't unreasonably high. That's reducing
the estimated cost of accessing the large table via indexscans, and
I'm thinking it reduced it too much.
regards, tom lane
2011/6/8 Tony Capobianco <tcapobianco@prospectiv.com>: > pg_dw=# show random_page_cost ; > random_page_cost > ------------------ > 4 > (1 row) > > Time: 0.299 ms > pg_dw=# show seq_page_cost ; > seq_page_cost > --------------- > 1 > (1 row) > > Time: 0.250 ms > pg_dw=# show work_mem ; > work_mem > ---------- > 768MB > (1 row) > > it is ok. Pavel > > > On Wed, 2011-06-08 at 18:27 +0200, Pavel Stehule wrote: >> Hello >> >> what is your settings for >> >> random_page_cost, seq_page_cost and work_mem? >> >> Regards >> >> Pavel Stehule >> >> 2011/6/8 Tony Capobianco <tcapobianco@prospectiv.com>: >> > Here's the explain analyze: >> > >> > pg_dw=# explain analyze CREATE TABLE ecr_opens with (FILLFACTOR=100) >> > as >> > select o.emailcampaignid, count(memberid) opencnt >> > from openactivity o,ecr_sents s >> > where s.emailcampaignid = o.emailcampaignid >> > group by o.emailcampaignid; >> > >> > QUERY >> > PLAN >> > ---------------------------------------------------------------------------------------------------------------------------------------------------------------- >> > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) (actual >> > time=308630.967..2592279.526 rows=472 loops=1) >> > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) >> > (actual time=31.489..2589363.047 rows=8586466 loops=1) >> > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s >> > (cost=0.00..38.59 rows=479 width=4) (actual time=0.010..13.326 rows=479 >> > loops=1) >> > -> Index Scan using openact_emcamp_idx on openactivity o >> > (cost=0.00..3395.49 rows=19372 width=12) (actual time=1.336..5397.139 >> > rows=17926 loops=479) >> > Index Cond: (o.emailcampaignid = s.emailcampaignid) >> > Total runtime: 2592284.336 ms >> > >> > >> > On Wed, 2011-06-08 at 17:31 +0200, tv@fuzzy.cz wrote: >> >> > On Postgres, this same query takes about 58 minutes (could not run >> >> > explain analyze because it is in progress): >> >> > >> >> > pg_dw=# explain CREATE TABLE ecr_opens with (FILLFACTOR=100) >> >> > pg_dw-# as >> >> > pg_dw-# select o.emailcampaignid, count(memberid) opencnt >> >> > pg_dw-# from openactivity o,ecr_sents s >> >> > pg_dw-# where s.emailcampaignid = o.emailcampaignid >> >> > pg_dw-# group by o.emailcampaignid; >> >> > QUERY >> >> > PLAN >> >> > ------------------------------------------------------------------------------------------------------------- >> >> > GroupAggregate (cost=0.00..1788988.05 rows=9939 width=12) >> >> > -> Nested Loop (cost=0.00..1742467.24 rows=9279316 width=12) >> >> > -> Index Scan using ecr_sents_ecid_idx on ecr_sents s >> >> > (cost=0.00..38.59 rows=479 width=4) >> >> > -> Index Scan using openact_emcamp_idx on openactivity o >> >> > (cost=0.00..3395.49 rows=19372 width=12) >> >> > Index Cond: (o.emailcampaignid = s.emailcampaignid) >> >> > (5 rows) >> >> > >> >> >> >> Please, post EXPLAIN ANALYZE, not just EXPLAIN. Preferably using >> >> explain.depesz.com. >> >> >> >> regards >> >> Tomas >> >> >> >> >> > >> > >> > >> > -- >> > Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) >> > To make changes to your subscription: >> > http://www.postgresql.org/mailpref/pgsql-performance >> > >> > > >
My current setting is 22G. According to some documentation, I want to set effective_cache_size to my OS disk cache + shared_buffers. In this case, I have 4 quad-core processors with 512K cache (8G) and my shared_buffers is 7680M. Therefore my effective_cache_size should be approximately 16G? Most of our other etl processes are running fine, however I'm curious if I could see a significant performance boost by reducing the effective_cache_size. On Wed, 2011-06-08 at 13:03 -0400, Tom Lane wrote: > Tony Capobianco <tcapobianco@prospectiv.com> writes: > > Well, this ran much better. However, I'm not sure if it's because of > > set enable_nestloop = 0, or because I'm executing the query twice in a > > row, where previous results may be cached. I will try this setting in > > my code for when this process runs later today and see what the result > > is. > > If the performance differential holds up, you should look at adjusting > your cost parameters so that the planner isn't so wrong about which one > is faster. Hacking enable_nestloop is a band-aid, not something you > want to use in production. > > Looking at the values you gave earlier, I wonder whether the > effective_cache_size setting isn't unreasonably high. That's reducing > the estimated cost of accessing the large table via indexscans, and > I'm thinking it reduced it too much. > > regards, tom lane >
Tony Capobianco <tcapobianco@prospectiv.com> wrote: > According to some documentation, I want to set > effective_cache_size to my OS disk cache + shared_buffers. That seems reasonable, and is what has worked well for me. > In this case, I have 4 quad-core processors with 512K cache (8G) > and my shared_buffers is 7680M. Therefore my effective_cache_size > should be approximately 16G? I didn't follow that at all. Can you run `free` or `vmstat`? If so, go by what those say your cache size is. > Most of our other etl processes are running fine, however I'm > curious if I could see a significant performance boost by reducing > the effective_cache_size. Since it is an optimizer costing parameter and has no affect on memory allocation, you can set it on a connection and run a query on that connection to test the impact. Why wonder about it when you can easily test it? -Kevin
On Wed, Jun 8, 2011 at 12:03 PM, Tony Capobianco <tcapobianco@prospectiv.com> wrote:
My current setting is 22G. According to some documentation, I want to
set effective_cache_size to my OS disk cache + shared_buffers. In this
case, I have 4 quad-core processors with 512K cache (8G) and my
shared_buffers is 7680M. Therefore my effective_cache_size should be
approximately 16G? Most of our other etl processes are running fine,
however I'm curious if I could see a significant performance boost by
reducing the effective_cache_size.
disk cache, not CPU memory cache. It will be some significant fraction of total RAM on the host. Incidentally, 16 * 512K cache = 8MB, not 8GB.
Oooo...some bad math there. Thanks. On Wed, 2011-06-08 at 12:38 -0700, Samuel Gendler wrote: > > > On Wed, Jun 8, 2011 at 12:03 PM, Tony Capobianco > <tcapobianco@prospectiv.com> wrote: > My current setting is 22G. According to some documentation, I > want to > set effective_cache_size to my OS disk cache + > shared_buffers. In this > case, I have 4 quad-core processors with 512K cache (8G) and > my > shared_buffers is 7680M. Therefore my effective_cache_size > should be > approximately 16G? Most of our other etl processes are > running fine, > however I'm curious if I could see a significant performance > boost by > reducing the effective_cache_size. > > > > > > disk cache, not CPU memory cache. It will be some significant > fraction of total RAM on the host. Incidentally, 16 * 512K cache = > 8MB, not 8GB. > > > http://en.wikipedia.org/wiki/CPU_cache > > > >
> * Tony Capobianco (tcapobianco@prospectiv.com) wrote:
>> HashAggregate (cost=4391163.81..4391288.05 rows=9939 width=12)
>> -> Hash Join (cost=14.78..4344767.23 rows=9279316 width=12)
>> Hash Cond: (o.emailcampaignid = s.emailcampaignid)
>> -> Seq Scan on openactivity o (cost=0.00..3529930.67
>> rows=192540967 width=12)
>> -> Hash (cost=8.79..8.79 rows=479 width=4)
>> -> Seq Scan on ecr_sents s (cost=0.00..8.79 rows=479
>> width=4)
>>
>> Yikes. Two sequential scans.
>
> Err, isn't that more-or-less exactly what you want here? The smaller
> table is going to be hashed and then you'll traverse the bigger table
> and bounce each row off the hash table. Have you tried actually running
> this and seeing how long it takes? The bigger table doesn't look to be
> *that* big, if your i/o subsystem is decent and you've got a lot of
> memory available for kernel cacheing, should be quick.
Just out of curiosity, is there any chance that this kind of query is
speeding up in 9.1 because of following changes?
* Allow FULL OUTER JOIN to be implemented as a hash join, and allow
either side of a LEFT OUTER JOIN or RIGHT OUTER JOIN to be hashed
(Tom Lane)
Previously FULL OUTER JOIN could only be implemented as a merge
join, and LEFT OUTER JOIN and RIGHT OUTER JOIN could hash only the
nullable side of the join. These changes provide additional query
optimization possibilities.
--
Tatsuo Ishii
SRA OSS, Inc. Japan
English: http://www.sraoss.co.jp/index_en.php
Japanese: http://www.sraoss.co.jp
Tatsuo Ishii <ishii@postgresql.org> writes:
> Just out of curiosity, is there any chance that this kind of query is
> speeding up in 9.1 because of following changes?
> * Allow FULL OUTER JOIN to be implemented as a hash join, and allow
> either side of a LEFT OUTER JOIN or RIGHT OUTER JOIN to be hashed
> (Tom Lane)
The given query wasn't an outer join, so this wouldn't affect it.
regards, tom lane