合并与更新

时间:2016-02-04 08:57:28

标签: sql oracle performance merge sql-update

我试图在网上寻找,但无法找到任何能解决我疑虑的事情。

我想找出哪一个更好用,何时以及为什么?

我知道MERGE通常用于upsert,但在某些情况下,带子查询的正常更新必须从表中选择两次(一个来自where子句)。

E.G:

MERGE INTO TableA s
USING (SELECT sd.dwh_key,sd.serial_number from TableA@to_devstg sd
       where sd.dwh_key = s.dwh_key and sd.serial_number <> s.serial_number) t
ON(s.dwh_key = t.dwh_key)
WHEN MATCHED UPDATE SET s.serial_number = t.serial_number

在我的情况下,我必须根据另一个在serial_number字段上发生更改的环境中的同一个表,在一个环境中更新一个包含大约200mil记录的表。正如你所看到的,它从这张巨大的桌子中选择了一个。

另一方面,我可以像这样使用UPDATE STATEMENT:

UPDATE TableA s
SET s.serial_number = (SELECT t.serial_number
                       FROM TableA@to_Other t
                       WHERE t.dwh_serial_key = s.dwh_serial_key)
WHERE EXISTS (SELECT 1
              FROM TableA@To_Other t
              WHERE t.dwh_serial_key = s.dwh_serial_key
              AND t.serial_number <> s.serial_number)   

正如你所看到的,现在从巨大的表中选择两次。所以,我的问题是,什么更好?为什么?..哪一个案例会比另一个好......

提前致谢。

1 个答案:

答案 0 :(得分:1)

我首先尝试将所有必要的数据从远程数据库加载到临时表,然后使用该临时表。

    // The productions describing this are:
    $a   = '[a-z]';     // alpha
    $an  = '[a-z0-9]';  // alphanum
    $and = "[a-z0-9-$underscore]"; // alphanum | "-"
    // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
    $domainlabel = "$an($and*$an)?";
    // toplabel    = alpha | alpha *( alphanum | "-" ) alphanum
    $toplabel = "$a($and*$an)?";
    // hostname    = *( domainlabel "." ) toplabel [ "." ]
    if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
        return $string;
    }