【发布时间】:2017-11-17 11:01:14
【问题描述】:
在这个查询中,我们执行从一个大表release 到两个表release_event 和release_barcode 的外连接。这些必须是外连接,因为在结果中我们希望返回在任一表中都没有条目的版本:
SELECT r.source_uri AS su_on_r, r.title AS t_on_r, release_event.cat, release_barcode.barcode
FROM release r
left join release_event event ON r.source_uri = event.source_uri
left join release_barcode barcode ON r.source_uri = barcode.source_uri
WHERE ( event.cat IN ( '3145422912' ) AND event.label_name = 'UTV Records' )
OR barcode.barcode IN ( '731454229128' )
分析时,这会对release 表执行顺序扫描:
| -> Sort (cost=2169219.61..2169219.65 rows=13 width=66) |
| Sort Key: r.source_uri |
| -> Hash Left Join (cost=721970.94..2169219.37 rows=13 width=66) |
| Hash Cond: ((r.source_uri)::text = (barcode.source_uri)::text) |
| Filter: ((((event.cat)::text = '3145422912'::text) AND ((event.label_name)::text = 'UTV Records'::text)) OR ((barcode.barcode)::text = '731454229128'::text)) |
| -> Hash Right Join (cost=589927.01..1568193.22 rows=11405330 width=88) |
| Hash Cond: ((event.source_uri)::text = (r.source_uri)::text) |
| -> Seq Scan on release_event event (cost=0.00..283078.30 rows=11405330 width=65) |
| -> Hash (cost=324393.56..324393.56 rows=10963956 width=66) |
| -> Seq Scan on release r (cost=0.00..324393.56 rows=10963956 width=66) |
| -> Hash (cost=63125.97..63125.97 rows=2965197 width=60) |
| -> Seq Scan on release_barcode barcode (cost=0.00..63125.97 rows=2965197 width=6
如果我只有上述条件之一,查询规划器 (Postgresql) 会理解这一点,使用索引来限制来自 release 的结果:
| -> Sort (cost=42.26..42.27 rows=3 width=66) |
| Sort Key: r.source_uri |
| -> Nested Loop (cost=0.99..42.24 rows=3 width=66) |
| -> Index Scan using release_barcode_barcode_idx on release_barcode barcode (cost=0.43..16.47 rows=3 width=47) |
| Index Cond: ((barcode)::text = '731454229128'::text) |
| -> Index Scan using release_pkey on release r (cost=0.56..8.58 rows=1 width=66) |
| Index Cond: ((source_uri)::text = (barcode.source_uri)::text)
如何使用外部联接和多个 OR'd 条件重写查询,以首先限制联接的表,并仅在 release 表中查找任何匹配的行?
【问题讨论】:
-
不相关,但是:外部联接表上的
where子句将您的外部联接变成内部联接 -
差不多,有一个 OR。
标签: sql postgresql