From: | "Phoenix Kiula" <phoenix(dot)kiula(at)gmail(dot)com> |
---|---|
To: | "Postgres General" <pgsql-general(at)postgresql(dot)org> |
Subject: | JOIN issues (Left vs Right for sorting), and "Nested Loop" problem |
Date: | 2007-09-01 09:46:09 |
Message-ID: | e373d31e0709010246qa72cd21ne8ca167380b0c1bf@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
Hello,
I have a simple query as follows. It joins two very straightforward tables.
SELECT
trades.id,
trades.url,
trades.alias,
tradecount.t_count,
tradecount.u_count
FROM trades
LEFT JOIN tradecount ON trades.id = tradecount.id
WHERE trades.user_id = 'jondoe' and trades.status = 'Y'
ORDER BY
tradecount.u_count desc
OFFSET 20 LIMIT 10
Both the tables have a bigint "id" field that connects them. The table
definitions are included below:
Table "public.trades"
Column | Type | Modifiers
-----------------------+-----------------------------+------------------------------
id | bigint | not null
user_id | character varying(45) | not null
url | text | not null
alias | character varying(20) | not null
title | character varying(500) |
private | character(1) |
status | character(1) | default 'Y'::bpchar
modify_date | timestamp without time zone |
disable_in_statistics | character(1) | not null
default 'N'::bpchar
Indexes:
"trades_pkey" PRIMARY KEY, btree (id)
"trades_unique_alias" UNIQUE, btree (alias)
"idx_trades_mdate" btree (modify_date)
"idx_trades_userid" btree (user_id)
Check constraints:
"trades_alias_valid" CHECK (alias::text ~ '[-A-Za-z0-9_]'::text)
"trades_id_check" CHECK (id > 0)
"trades_url_check" CHECK (url <> ''::text)
"trades_user_id_check" CHECK (user_id::text <> ''::text)
Table "public.tradecount"
Column | Type | Modifiers
--------------+-----------------------------+--------------------
id | bigint | not null
t_count | integer | not null default 0
u_count | integer | not null default 0
modify_date | timestamp without time zone | default now()
Indexes:
"tradecount_pkey" PRIMARY KEY, btree (id)
"i_tradecount_uc" btree (u_count)
"i_tradecount_vc" btree (t_count)
Foreign-key constraints:
"fk_tradecount_trades_id" FOREIGN KEY (id) REFERENCES trades(id)
ON DELETE CASCADE
Rules:
replace_tradecount_on_duplicate_insert AS
ON INSERT TO tradecount
WHERE (EXISTS ( SELECT 1
FROM tradecount
WHERE tradecount.id = new.id)) DO INSTEAD UPDATE tradecount
SET t_count = tradecount.t_count, u_count = tradecount.u_count
WHERE tradecount.id = new.id
Now I have two problems:
1. The above query takes more time to fire up that an index should
really take. I have bitmap heap scan off in conf file, and indexscan
on, otherwise this was going into a bitmap heap thing.
As you will see from the SQL above, the trades.user_id index should be
limiting the number of rows to a few hundred (or thousand at max) and
then we are trying to get only 10 tuples based on the OFFSET and LIMIT
clauses.
However, there's a nested loop in there as the EXPLAIN ANALYZE shows
below. What is causing this nested loop?
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Limit (cost=4829.70..4829.73 rows=10 width=125) (actual
time=9.784..9.835 rows=10 loops=1)
-> Sort (cost=4829.65..4830.61 rows=385 width=125) (actual
time=9.703..9.757 rows=30 loops=1)
Sort Key: tradecount.u_count
-> Nested Loop Left Join (cost=0.00..4813.12 rows=385
width=125) (actual time=0.075..8.662 rows=386 loops=1)
-> Index Scan using idx_trades_userid on trades
(cost=0.00..1556.08 rows=385 width=117) (actual time=0.05
0..1.225 rows=386 loops=1)
Index Cond: ((user_id)::text = 'jondoe'::text)
Filter: (status = 'Y'::bpchar)
-> Index Scan using tradecount_pkey on tradecount
(cost=0.00..8.45 rows=1 width=16) (actual time=0.006.
.0.008 rows=1 loops=386)
Index Cond: (trades.id = tradecount.id)
Total runtime: 9.963 ms
(10 rows)
2. Secondly, if I want to sort the join by a column on the second
table, then the rows returned are not really sorted unless I do a
RIGHT JOIN (my sql above shows a LEFT JOIN). Getting results from a
right join is fine as long as the column is not null in the second
table, but if it is null, then nothing is returned. This is why I do a
LEFT join in the first place! So my question: how can I do a left
join, which is the logic that I wish to accomplish, but get the
sorting to work from the second table and if a column is null then
just return as 0 instead of nothing at all? (The LEFT JOIN used to
work in Mysql).
TIA for any thoughts!
From | Date | Subject | |
---|---|---|---|
Next Message | Ron Johnson | 2007-09-01 10:08:41 | Re: Export data to MS Excel |
Previous Message | Phoenix Kiula | 2007-09-01 09:23:38 | Re: Export data to MS Excel |