我知道我们对此有很多疑问,但我的具体针对Oracle。我一直认为使用join更快的性能。但是今天,我有2个返回相同数据的查询,但是一个使用join,一个是嵌套的。解释计划显示嵌套查询的成本更好。我不知道该怎么想。我何时应该使用嵌套查询?何时不应该?我们正在使用Oracle 11.2。
以下是每个解释计划的文字:
select (select p.organization_code from apps.mtl_parameters p where p.organization_id = ship_from_org_id)
from ont.OE_ORDER_LINES_all l
where header_id = (select header_id from ont.oe_order_headers_all where order_number = '9000385403')
and l.ordered_item = 'SSFRAMES';
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 21 | 120 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID | MTL_PARAMETERS | 1 | 8 | 1 (0)|
| 2 | INDEX UNIQUE SCAN | MTL_PARAMETERS_U1 | 1 | | 0 (0)|
| 3 | TABLE ACCESS BY INDEX ROWID | OE_ORDER_LINES_ALL | 1 | 21 | 116 (0)|
| 4 | INDEX RANGE SCAN | XXOE_ORDER_LINES_ALL_X6 | 586 | | 6 (0)|
| 5 | TABLE ACCESS BY INDEX ROWID| OE_ORDER_HEADERS_ALL | 1 | 12 | 4 (0)|
select p.organization_code
from ont.OE_ORDER_LINES_all l
inner join ont.oe_order_headers_all oha on oha.header_id = l.header_id
inner join apps.mtl_parameters p on p.organization_id = l.ship_from_org_id
where l.ordered_item = 'SSFRAMES' and oha.order_number = '9000385403'
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 41 | 119 (0)|
| 1 | NESTED LOOPS | | | | |
| 2 | NESTED LOOPS | | 1 | 41 | 119 (0)|
| 3 | NESTED LOOPS | | 1 | 33 | 118 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID| OE_ORDER_HEADERS_ALL | 1 | 12 | 4 (0)|
| 5 | INDEX RANGE SCAN | OE_ORDER_HEADERS_U2 | 1 | | 3 (0)|
| 6 | TABLE ACCESS BY INDEX ROWID| OE_ORDER_LINES_ALL | 1 | 21 | 114 (0)|
| 7 | INDEX RANGE SCAN | OE_ORDER_LINES_N1 | 586 | | 3 (0)|
| 8 | INDEX UNIQUE SCAN | MTL_PARAMETERS_U1 | 1 | | 0 (0)|
| 9 | TABLE ACCESS BY INDEX ROWID | MTL_PARAMETERS | 1 | 8 | 1 (0)|
select p.organization_code
from ont.OE_ORDER_LINES_all l
inner join ont.oe_order_headers_all oha on l.header_id in oha.header_id
inner join apps.mtl_parameters p on p.organization_id in l.ship_from_org_id
where l.ordered_item = 'SSFRAMES' and oha.order_number = '9000385403';
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 40 | 115 (0)|
| 1 | NESTED LOOPS | | | | |
| 2 | NESTED LOOPS | | 1 | 40 | 115 (0)|
| 3 | NESTED LOOPS | | 1 | 32 | 114 (0)|
| 4 | TABLE ACCESS BY INDEX ROWID| OE_ORDER_HEADERS_ALL | 1 | 11 | 4 (0)|
| 5 | INDEX RANGE SCAN | OE_ORDER_HEADERS_U2 | 1 | | 3 (0)|
| 6 | TABLE ACCESS BY INDEX ROWID| OE_ORDER_LINES_ALL | 1 | 21 | 110 (0)|
| 7 | INDEX RANGE SCAN | XXOE_ORDER_LINES_ALL_X6 | 582 | | 5 (0)|
| 8 | INDEX UNIQUE SCAN | MTL_PARAMETERS_U1 | 1 | | 0 (0)|
| 9 | TABLE ACCESS BY INDEX ROWID | MTL_PARAMETERS | 1 | 8 | 1 (0)|
答案 0 :(得分:1)
只是查看解释计划不会给你什么查询实际上更快执行。它仅仅是优化器猜测给出的当前信息。
此外,基数猜测错误往往会传播到更高级别的操作。例如。您在SELECT子句中放置的子选择仅对整个语句计算一次,但当然应该计入每个要返回的预期记录。
最后,相等连接的等价物是IN(...)条件而不是a =(...)条件。