Postgres Optimizer is not smart enough? - Mailing list pgsql-performance
From | Litao Wu |
---|---|
Subject | Postgres Optimizer is not smart enough? |
Date | |
Msg-id | 20050112222506.32084.qmail@web13124.mail.yahoo.com Whole thread Raw |
Responses |
Re: Postgres Optimizer is not smart enough?
Re: Postgres Optimizer is not smart enough? |
List | pgsql-performance |
Hi All, Here is my test comparison between Postgres (7.3.2) optimizer vs Oracle (10g) optimizer. It seems to me that Postgres optimizer is not smart enough. Did I miss anything? Thanks, In Postgres: ============ drop table test; create table test ( module character varying(50), action_deny integer, created timestamp with time zone, customer_id integer, domain character varying(255)); create or replace function insert_rows () returns integer as ' BEGIN for i in 1 .. 500000 loop insert into test values (i, 2, now(), 100, i); end loop; return 1; END; ' LANGUAGE 'plpgsql'; select insert_rows(); create index test_id1 on test (customer_id, created, domain); analyze test; explain analyze SELECT module, sum(action_deny) FROM test WHERE created >= ('now'::timestamptz - '1 day'::interval) AND customer_id='100' AND domain='100' GROUP BY module; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=3.12..3.13 rows=1 width=9) (actual time=91.05..91.05 rows=1 loops=1) -> Group (cost=3.12..3.12 rows=1 width=9) (actual time=91.04..91.04 rows=1 loops=1) -> Sort (cost=3.12..3.12 rows=1 width=9) (actual time=91.03..91.03 rows=1 loops=1) Sort Key: module -> Index Scan using test_id1 on test (cost=0.00..3.11 rows=1 width=9) (actual time=0.03..91.00 rows=1 loops=1) Index Cond: ((customer_id = 100) AND (created >= '2005-01-11 14:48:44.832552-07'::timestamp with time zone) AND ("domain" = '100'::character varying)) Total runtime: 91.13 msec (7 rows) create index test_id2 on test(domain); analyze test; explain analyze SELECT module, sum(action_deny) FROM test WHERE created >= ('now'::timestamptz - '1 day'::interval) AND customer_id='100' AND domain='100' GROUP BY module; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=3.12..3.13 rows=1 width=9) (actual time=90.30..90.30 rows=1 loops=1) -> Group (cost=3.12..3.12 rows=1 width=9) (actual time=90.29..90.30 rows=1 loops=1) -> Sort (cost=3.12..3.12 rows=1 width=9) (actual time=90.29..90.29 rows=1 loops=1) Sort Key: module -> Index Scan using test_id1 on test (cost=0.00..3.11 rows=1 width=9) (actual time=0.03..90.25 rows=1 loops=1) Index Cond: ((customer_id = 100) AND (created >= '2005-01-11 14:51:09.555974-07'::timestamp with time zone) AND ("domain" = '100'::character varying)) Total runtime: 90.38 msec (7 rows) WHY PG STILL CHOOSE INDEX test_id1??? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ BECAUSE QUERY WILL RUN MUCH FASTER USING test_id2!!! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ drop index test_id1; explain analyze SELECT module, sum(action_deny) FROM test WHERE created >= ('now'::timestamptz - '1 day'::interval) AND customer_id='100' AND domain='100' GROUP BY module; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Aggregate (cost=3.12..3.13 rows=1 width=9) (actual time=0.08..0.08 rows=1 loops=1) -> Group (cost=3.12..3.13 rows=1 width=9) (actual time=0.08..0.08 rows=1 loops=1) -> Sort (cost=3.12..3.13 rows=1 width=9) (actual time=0.07..0.07 rows=1 loops=1) Sort Key: module -> Index Scan using test_id2 on test (cost=0.00..3.11 rows=1 width=9) (actual time=0.04..0.05 rows=1 loops=1) Index Cond: ("domain" = '100'::character varying) Filter: ((created >= '2005-01-11 14:53:58.806364-07'::timestamp with time zone) AND (customer_id = 100)) Total runtime: 0.14 msec (8 rows) In Oracle: ========== drop table test; create table test ( module character varying(50), action_deny integer, created timestamp with time zone, customer_id integer, domain character varying(255)); begin for i in 1..500000 loop insert into test values (i, 2, current_timestamp, 100, i); end loop; end; / create index test_id1 on test (customer_id, created, domain); analyze table test compute statistics; set autot on set timing on SELECT module, sum(action_deny) FROM test WHERE created >= (current_timestamp - interval '1' day) AND customer_id=100 AND domain='100' GROUP BY module / MODULE SUM(ACTION_DENY) -------------------------------------------------- ---------------- 100 2 Elapsed: 00:00:00.67 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=25 Card=1 Bytes=29 ) 1 0 SORT (GROUP BY) (Cost=25 Card=1 Bytes=29) 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (TABLE) (Cost=24 Card=1 Bytes=29) 3 2 INDEX (RANGE SCAN) OF 'TEST_ID1' (INDEX) (Cost=23 Card =4500) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 2292 consistent gets 2291 physical reads 0 redo size 461 bytes sent via SQL*Net to client 508 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1 rows processed create index test_id2 on test (domain); SELECT module, sum(action_deny) FROM test WHERE created >= (current_timestamp - interval '1' day) AND customer_id=100 AND domain='100' GROUP BY module / MODULE SUM(ACTION_DENY) -------------------------------------------------- ---------------- 100 2 Elapsed: 00:00:00.03 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=5 Card=1 Bytes=29) 1 0 SORT (GROUP BY) (Cost=5 Card=1 Bytes=29) 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (TABLE) (Cost=4 Card=1 Bytes=29) 3 2 INDEX (RANGE SCAN) OF 'TEST_ID2' (INDEX) (Cost=3 Card= 1) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 461 bytes sent via SQL*Net to client 508 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1 rows processed __________________________________ Do you Yahoo!? All your favorites on one personal page � Try My Yahoo! http://my.yahoo.com
pgsql-performance by date: