0

表 X

number doc
number item
number parentItem

有数据:

1, 1000, 0
1, 1010, 1000
1, 1020, 1000
1, 2000, 0
1, 2010, 2000


表Y

number doc
number item
varchar2(16) SomeData

有数据:

1, 1000, "1000 Data"
1, 2000, "2000 Data"


我使用以下 SQL 查询从 TableY 中获取“SomeData”

select x.doc, x.item, y.SomeData from TableX x
join TableY y
on y.doc = x.doc and y.item IN (x.item, x.ParentItem)

这应该导致:

1, 1000, "1000 Data"
1, 1010, "1000 Data"
1, 1020, "1000 Data"
1, 2000, "2000 Data"
1, 2010, "2000 Data"

我的问题是:IN-Statement是按顺序评估的,还是取决于 Oracle 采用的路径?


编辑 我的意思是当 TableY 中有来自 TableX 的项目的条目(如 1000)时,该值将首先在 JOIN 中使用还是将首先使用 ParentItem?还是仅在项目上的 JOIN 失败时才完成 ParentItem 上的 JOIN ?

4

2 回答 2

4

通常,在使用数据库时,除非您指定一个,否则没有顺序。我相信IN总是检查整个列表而不是在找到匹配项时进行短路,但是不能保证列表的处理顺序(如果它检查整个列表并不重要)。


根据您修改后的问题:

Oracle 无法根据行包含的内容创建执行计划,因此优化器将开发一个计划,以尽可能最有效的方式查找两列。该计划将在很大程度上取决于您的表的大小和您创建的索引。

处理一次表几乎总是更快,因此优化器可能会选择一种可以轻松检查两列的路径,而不是必须一次检查列的路径。这意味着,除非它有更好的途径,否则可能会进行全表扫描。一个小实验告诉我,即使有一个索引覆盖两列,优化器也会选择全表扫描。

有趣的是,这似乎是少数几个最好将两列分开索引的场景之一。如果两列上都有单独的索引,则优化器似乎将扫描这两个索引,然后使用 abitmap or从每个结果集中获取唯一的 rowid 集。

这里需要注意的是,我的研究是在我可用的大桌子上完成的,使用了高度人工的场景。您应该以最简单、最容易阅读(和维护)的方式构建您的查询,然后测试它的实际性能并自己查看它的解释计划。只有当您确定存在性能问题(或可能存在)时,您才应该担心寻找另一种更有效(但可能不那么自我解释)的查询编写方式。一般来说,如果你有一个经过深思熟虑的、可搜索的查询,优化器会很好地选择最有效的可用路径。

于 2011-07-25T13:50:20.407 回答
0

评估顺序无关紧要。IN 语句只是说 . 的简写方法y.item = x.item OR y.item = x.ParentItem OR ...

于 2011-07-25T13:30:21.150 回答