这个问题是如何解决在子查询中与多个表进行半连接时明显的oracle限制。我有以下两个UPDATE语句:
更新1:UPDATE
(SELECT a.flag update_column
FROM a, b
WHERE a.id = b.id AND
EXISTS (SELECT NULL
FROM c
WHERE c.id2 = b.id2 AND
c.time BETWEEN start_in AND end_in) AND
EXISTS (SELECT NULL
FROM TABLE(update_in) d
WHERE b.time BETWEEN d.start_time AND d.end_time))
SET update_column = 'F'
执行计划表明这正确地执行了2个半连接,并且更新在几秒钟内执行。这些需要是半连接,因为c.id2
不是b.id2
上的唯一外键,不像b.id
和a.id
。update_in
没有任何约束,因为它是一个数组。
UPDATE
(SELECT a.flag update_column
FROM a, b
WHERE a.id = b.id AND
EXISTS (SELECT NULL
FROM c, TABLE(update_in) d
WHERE c.id2 = b.id2 AND
c.time > d.time AND
b.time BETWEEN d.start_time AND d.end_time))
SET update_column = 'F'
不执行半连接;根据Oracle文档,我相信这是因为EXISTS子查询中有2个表。由于表和分区的大小,此更新需要几个小时。然而,没有办法将d.time
关联到相关的d.start_time
和d.end_time
,除非它们在同一行上。我们传入update_in
数组并在这里连接它的原因是,对于每个time/start_time/end_time组合,在循环中运行此查询也证明了性能很差。
除了2个表之外,还有其他原因导致半连接不能工作吗?如果没有,有没有办法绕过这个限制?一些简单的解决方案,我错过了,可以使这些条件工作,而不把2个表在子查询?
正如Bob建议的,您可以使用与update_in数组结构相同的全局临时表(GTT),但关键的区别在于您可以在GTT上创建索引,并且如果您用代表性的示例数据填充GTT,您还可以收集表上的统计信息,以便SQL查询分析器能够更好地预测最佳查询计划。
也就是说,在你的两个查询中还有一些其他显著的差异:
- 在第一个查询的第一个exists子句中,您引用了两个列start_in和end_in,它们没有表引用。我的猜测是,它们要么是表a或b中的列,要么是sql语句当前范围内的变量。目前还不清楚。
- 在你的第二个查询中,你引用了列d.time,但是,你没有在第一个查询中使用该列。
将第二个查询更新为以下内容是否会提高它的性能?
UPDATE
(SELECT a.flag update_column
FROM a, b
WHERE a.id = b.id AND
EXISTS (SELECT NULL
FROM c, TABLE(update_in) d
WHERE c.id2 = b.id2 AND
c.time BETWEEN start_in AND end_in AND
c.time > d.time AND
b.time BETWEEN d.start_time AND d.end_time))
SET update_column = 'F'