使用子查询的SQL更新运行时间太长

时间:2015-08-31 20:44:03

标签: sql oracle performance subquery

我的SQL更新查询与我的测试数据一起运行,但没有完成(2小时或更长时间)我的生产数据。

查询的目的

我有一个ADDRESSES表,它使用代码字符串而不是ID。因此,例如ADDRESSES.COUNTRY_CODE =“USA”而不是3152.对于参照完整性,我将这些代码字符串更改为代码ID。

模式

ADDRESSES(约356,000条记录)

  • ADDR_ID(PK)
  • COUNTRY_CODE(varchar)
  • 地址第1行(varchar)

COUNTRY_CODES

  • CODE_ID(PK)
  • CODE_STRING(varchar)
  • 等。

步骤

首先,我创建一个临时表来存储具有相应代码ID的地址记录:

CREATE TABLE ADDRESS_TEMP
AS
   SELECT ADDR_ID, CODE_ID
     FROM    ADDRESSES
          LEFT JOIN
             COUNTRY_CODES
          ON ADDRESSES.COUNTRY_CODE = CODE_STRING

其次,我将COUNTRY_CODE列置空并将其类型更改为NUMBER。

第三,我将COUNTRY_CODE列设置为代码ID:

UPDATE ADDRESSES
   SET COUNTRY_CODE =
          (SELECT ADDRESS_TEMP.CODE_ID
             FROM ADDRESS_TEMP
            WHERE ADDRESS_TEMP.ADDR_ID = ADDRESSES.ADDR_ID)

这是第三步,需要数小时才能完成(2小时计算)。 ADDRESSES表有大约356,000条记录。没有错误;它还在运行。

问题

为什么这个更新查询没有完成?它效率极低吗?我想我可以看到子查询可能是一个N 2 算法,但我对SQL缺乏经验。

1 个答案:

答案 0 :(得分:3)

只是猜测Oracle Optimizer内部:'ADDRESS_TEMP'在addr_id上没有主键也没有任何索引。因此,更新确实采用n ^ 2方法。它基本上通过临时表扫描地址表中的每一行。

所以,建议:使addr_id成为临时表的主键。

如果这对我们提供Oracle优化器生成的执行树没有帮助。这将更清楚地了解幕后实际发生的事情。