假设有两个表:
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)由于索引更有效率,而解释计划实际上表明它是。 (1)的解释计划显示了两个表的索引访问。解释计划(2)显示了对ITEM的索引访问,但是对TRANSACTION的全表访问。
但是我的困境是,当我在一组非常大的数据上运行它们来计算实际性能时,(2) 比(1)快四倍!这有什么可能的原因?我为什么要选择(1)超过(2)? (我们决定选择(2)而不是(1)。)
答案 0 :(得分:1)
您最有可能从Scalar子查询缓存中获益。我最近在博客上发表了关于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
有许多相等的值,缓存可以起到非常积极的作用。
更多有用的信息可以在这里找到: