【发布时间】:2017-12-10 03:58:13
【问题描述】:
oracle 查询中的联合导致大量 FTS(全表扫描)和高行数我可以重写此查询的更好方法吗?
SELECT
tab1.a1,
tab1.a2 ,
tab2.b1,
tab2.b2
FROM tab1 ,tab2
where tab1.aid = tab2.aid
and tab1.bid = tab2.bid
UNION
SELECT
tab1.a1,
tab1.a2,
tab3.c1,
tab3.c2
FROM tab1 ,tab3
where tab1.cid = tab3.cid
and tab1.bid =tab3.bid;
解释计划看起来像这样..
| Id | Operation | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | 1845K| 61M| | 120K (1)| 00:00:05 |
| 1 | UNION-ALL | | | | | |
| 2 | MERGE JOIN | 1719K| 57M| | 98522 (2)| 00:00:04 |
| 3 | SORT JOIN | 1761K| 25M| 94M| 30984 (1)| 00:00:02 |
| 4 | TABLE ACCESS FULL | 1761K| 25M| | 21911 (1)| 00:00:01 |
|* 5 | SORT JOIN | 1882K| 35M| 115M| 67538 (2)| 00:00:03 |
| 6 | TABLE ACCESS FULL | 1882K| 35M| | 56061 (2)| 00:00:03 |
| 7 | NESTED LOOPS | 126K| 3699K| | 22186 (1)| 00:00:01 |
| 8 | NESTED LOOPS | 126K| 3699K| | 22186 (1)| 00:00:01 |
| 9 | TABLE ACCESS FULL | 126K| 1726K| | 3232 (2)| 00:00:01 |
索引在 (tab1 (aid,bid), tab2(aid,bid) , tab3(cid,bid))
【问题讨论】:
-
您的查询没有
WHERE子句。所以这是所有的 tab1 记录,可能还有很多很多的 tab2 和 tab3 记录。因此,全表扫描似乎是读取表的最佳方法,而不是混淆索引,最终得到大多数记录。不过,您的查询混淆了它的真正任务。 user5480949 的回答显示了一个更清晰的查询。 -
您使用的是我们在 1980 年代使用的连接语法。甲骨文采用它很晚,但那仍然是大约 2001 年!你不应该再使用它了。改用正确的 ANSI 连接,例如
from tab1 inner join tab2 on tab1.aid = tab2.aid and tab1.bid = tab2.bid.
标签: sql oracle plsql oracle11g oracle12c