【发布时间】:2013-12-18 02:22:20
【问题描述】:
出于明显的性能原因,我想重写一个现有的 Oracle SQL 查询,其中包括涉及“not in”子句的相关子查询。这可以通过外部连接或其他一些技术来实现吗?
代码如下:
SELECT TRIM(et.event_id), TRIM(et.cancel_evt_id)
FROM external_transactions et
JOIN transaction_type tt
ON et.transaction_type_id = tt.transaction_type_id
WHERE et.acct = 'ABCDEF'
AND tt.transaction_type_class != 'XYZXYZ'
AND
(
TRIM(et.event_id) NOT IN
(
SELECT TRIM(t1.transaction_evt_id)
FROM transactions t1
WHERE t1.acct = et.acct
AND t1.asset_id = et.asset_id
AND t1.cancel_flag = 'N'
)
OR TRIM(et.cancel_evt_id) NOT IN
(
SELECT TRIM(t2.cancel_evt_id)
FROM transactions t2
WHERE t2.acct = et.acct
AND t2.asset_id = et.asset_id
AND t2.cancel_flag = 'Y'
)
)
;
【问题讨论】:
-
“明显的原因”是什么?我怀疑在 id 上使用
trim()会使查询的效率低于其他情况。 -
发布你的执行计划。
-
进行左连接并应用列的 WHERE IS NULL 通常要快得多。然而,话虽这么说......“et.event_id”和“t1.transaction_evt_id”的实际数据类型是什么。如果是数字,执行 TRIM() 是不好的,正如 Gordon 所说的那样。
-
在等上,列是 varchar2(55)。在 t 上,列是 varchar2(255)。这些模式可能是在不同时间创建的。为了快速取胜,我将尝试删除 trim() 语句,看看它们是否在逻辑上是必要的。但我怀疑我需要更显着地重组查询。表/字段名称已重命名以保护我客户的数据,因此我将无法发布解释计划。
-
@DRapp 我没有遇到与相关子查询相关的性能问题。如果 Oracle CBO 认为这会产生更好的性能计划,它可能会选择将关联子查询重写为底层连接。请参阅此Ask Tom 回复。我说写查询,这样它就清楚了,让 CBO 做这件事很神奇。
标签: sql oracle correlated-subquery