Oracle在SQL子查询中半连接多个表

时间:2015-06-03 23:37:30

标签: sql oracle semi-join

这个问题是如何解决子查询中具有多个表的半连接的明显oracle限制。我有以下2个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.ida.id不同。并且update_in根本没有任何约束,因为它是一个数组。

更新2:

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_timed.end_time相关联。我们传递update_in数组并在此处加入它的原因是因为在每次/ start_time / end_time组合的循环中运行此查询也会导致性能不佳。

除了2个表之外还有一个原因是半连接可能无法正常工作吗?如果没有,是否有办法绕过这个限制?我遗漏的一些简单的解决方案可以使这些标准无需在子查询中放置2个表吗?

1 个答案:

答案 0 :(得分:0)

正如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'