代码之家  ›  专栏  ›  技术社区  ›  Jordan Parmer

如何提高集合中包含昂贵聚合子查询的SQL更新语句的性能?

  •  0
  • Jordan Parmer  · 技术社区  · 17 年前

    我有以下更新方案:

    UPDATE destTable d
    SET d.test_count = ( SELECT COUNT( employee_id )
                         FROM sourceTable s
                         WHERE d.matchCode1 = s.matchCode1 AND
                               d.matchCode2 = s.matchCode2 AND
                               d.matchCode3 = s.matchCode3 
                         GROUP BY matchCode1, matchCode2, matchCode3, employee_id )
    

    我必须在一个循环中执行这个操作,为每个迭代更改匹配代码。

    在两个大表之间(每个约500k条记录),执行此查询需要很长的时间。如果我只执行一次,我不会太在意。考虑到它被执行了大约20次,这对我的需要来说太长了。

    它需要两个完整的表扫描(一个用于desttable,另一个用于子查询)。

    问题:

    1. 你推荐什么技术来加快速度?

    2. SQL优化器是否为我在desttable中更新的每一行运行子查询,以满足子查询的WHERE子句,或者它是否具有一次完成这一切的超级智能?

    3 回复  |  直到 13 年前
        1
  •  4
  •   Quassnoi    17 年前

    Oracle 9i 更高:

    MERGE   
    INTO    destTable d
    USING   (
            SELECT  matchCode1, matchCode2, matchCode3, COUNT(employee_id) AS cnt
            FROM    sourceTable s
            GROUP BY
                    matchCode1, matchCode2, matchCode3, employee_id
            ) so
    ON      d.matchCode1 = s.matchCode1 AND
            d.matchCode2 = s.matchCode2 AND
            d.matchCode3 = s.matchCode3 
    WHEN MATCHED THEN
    UPDATE
    SET     d.test_count = cnt
    

    要加快查询速度,请确保在 (matchCode1, matchCode2, matchCode3) 在里面 destTable 和上的复合索引 (matchCode1, matchCode2, matchCode3, employee_id) 在里面 sourceTable

        2
  •  3
  •   Joel Coehoorn    17 年前

    我必须在一个循环中执行这个

    您要做的第一件事是将循环构建到子查询或WHERE子句中。您正在更新数据,然后立即替换刚更新的部分数据。您应该能够过滤您的更新以仅更改适合当前迭代的记录,或者使您的查询足够复杂以更新一条语句中的所有内容——可能两者都是。

        3
  •  0
  •   JayTee    17 年前

    您考虑过从查询更新吗?