【问题标题】:Nested inline query faster than Equal Join嵌套内联查询比 Equal Join 更快
【发布时间】:2013-05-23 08:58:45
【问题描述】:

假设有两个表:

TRANSACTION
Primary Key: REF_NO
Columns:     REF_NO, TXN_DATE, ITEM_CODE, QUANTITY

ITEM
Primary Key: ITEM_CODE
Columns:     ITEM_CODE, ITEM_DESC

查询(1):

SELECT T.REF_NO, T.TXN_DATE, T.ITEM_CODE,
    I.ITEM_DESC,
    T.QUANTITY
FROM TRANSACTION T, ITEM I
WHERE T.ITEM_CODE = I.ITEM_CODE

查询(2):

SELECT T.REF_NO, T.TXN_DATE, T.ITEM_CODE,
    (SELECT ITEM_DESC FROM ITEM WHERE ITEM_CODE = T.ITEM_CODE) AS ITEM_DESC,
    T.QUANTITY
FROM TRANSACTION T

索引(索引)根据需要在两个表上。

以上是我正在做的事情的一个非常简化的版本,但概念是一样的。

有人告诉我,(1)由于索引而更有效,Explain Plan 实际上表明确实如此。 (1)的解释计划显示了两个表的索引访问。 (2) 的解释计划显示对 ITEM 的索引访问,但对 TRANSACTION 的全表访问。

但我的困境是,当我在非常大的数据集上运行它们以计算实际性能时,(2) 比 (1) 快 四倍!可能的原因是什么?为什么我应该选择(1)而不是(2)? (我们决定选择(2)而不是(1)。

【问题讨论】:

  • 我错过了基数,但 (2) 的成本要高得多,这非常令人费解。 (不在系统再次测试。)

标签: sql performance oracle


【解决方案1】:

您很可能从标量子查询缓存中获益。我最近在博客中介绍了 Oracle 11g(或 10g?)的这一令人敬畏的新特性:

http://blog.jooq.org/2011/09/02/oracle-scalar-subquery-caching

查看您的执行计划,您会在计划的顶部发现一些奇怪的元素,这表明实际的子查询并未真正针对源自TRANSACTIONS 表的每一行进行评估。这是因为Oracle's CBO introspects constraint metadata 推导出TRANSACTIONS 中的每一行在ITEMS 中只能有一个匹配行,如果使用ITEM_CODE 等值连接。这些知识使您的子查询受到缓存的影响。如果TRANSACTIONS.ITEM_CODE 有许多相等的值,缓存可以产生非常积极的效果。

更多有用的信息可以在这里找到:

【讨论】:

  • 问题是,我测试的数据库是 Oracle 10g。此外,即使您有WHERE ITEM_CODE = T.ITEM_CODE,也会发生子查询缓存吗?询问,因为 T 中该列的每一行中的数据可能不同。
  • 嗯,实际上我已经不确定了,什么时候介绍的。似乎找不到任何权威来源。无论如何,是的,它确实有效,因为您拥有ITEM_CODE = T.ITEM_CODE。约束元数据在 Oracle 决定此特定子查询是否可缓存方面发挥作用。 IE。 Oracle 知道,对于TRANSACTION 中的每一行,如果使用ITEM_CODE 连接,ITEM 中只能有一行。所以如果T.ITEM_CODE中有很多相似的值,缓存可以产生积极的影响。
  • 我认为它可能已经在 10g 中引入。通过阅读您的 oracle.com 链接,我了解它解释了 (2) 的更高速度,正如您在评论中所解释的那样。 (考虑将评论中的解释移至答案正文。)
猜你喜欢
  • 2018-10-14
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 2013-02-11
  • 2015-06-16
  • 2016-03-21
  • 1970-01-01
相关资源
最近更新 更多