1

这个问题是如何解决子查询中具有多个表的半连接的明显 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.idand不同a.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_time和。d.end_time我们传入update_in数组并在这里加入它的原因是因为在循环中为每个 time/start_time/end_time 组合运行此查询也证明性能很差。

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

4

1 回答 1

0

正如 Bob 建议的那样,您可以使用与 update_in 数组具有相同结构的全局临时表 (GTT),但关键区别在于您可以在 GTT 上创建索引,如果您使用代表性样本数据填充 GTT,您还可以收集有关表的统计信息,以便 SQL 查询分析器能够更好地预测最佳查询计划。

也就是说,您的两个查询中还有一些其他显着差异:

  • 在第一个查询的第一个存在子句中,您引用了两个没有表引用的列 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'
于 2015-06-24T20:52:06.553 回答