2012-03-23 62 views
2

除了连接之外,还有其他更快的方式进行更新吗?这里是我的查询,但它是一个有点慢:SQL更新加入

UPDATE @user_dupes 
    SET ExternalEmail = ud2.Email 
FROM @user_dupes ud1 
INNER JOIN(
SELECT Email, UserName 
    FROM @user_flat_emailtable_dupes 
WHERE EmailType = 2 
    AND Email IS NOT NULL AND LEN(Email) > 0 
) ud2 
ON ud1.UserName = ud2.UserName 

感谢您的任何想法

+0

是那些表变量?桌子的大小是多少? – Locksfree 2012-03-23 17:14:04

+0

这些是表变量。这是如何编码连接的更新。这是t-sql。这工作正常,但有点慢。试图看看是否有更快的方法可以基于另一个表来完成批量更新。 – 2012-03-23 17:18:37

+0

根据可变表中数据的大小,您可能需要使用临时表。通常,它们对大型数据集执行更好。你可以为它们编制索引。 – HLGEM 2012-03-23 17:33:51

回答

4

如果您正在使用SQL Server,你几乎没有。这只是一个小的解决办法:

UPDATE ud1 --little fix here! 
    SET ExternalEmail = ud2.Email 
FROM @user_dupes ud1 
INNER JOIN 
(
SELECT Email, UserName 
    FROM @user_flat_emailtable_dupes 
WHERE EmailType = 2 
    AND Email IS NOT NULL AND LEN(Email) > 0 
) ud2 
ON ud1.UserName = ud2.UserName 
+0

+1:很好的地方。此外,应该建议OP确保存在正确的索引,即使在表变量上也是如此,以确保连接的高效性。 – MatBailie 2012-03-23 17:21:15

+0

有趣。我会检查一下。现在运行更新的查询...谢谢 – 2012-03-23 17:22:42

+0

是的,我也会检查索引。谢谢 – 2012-03-23 17:23:26

4

一些改动,在什么@Adrian所述顶部...

UPDATE 
    ud1 -- @Adrian's change. Update the instance that you have already aliased. 
SET 
    externalEmail = ud2.Email 
FROM 
    @user_dupes     AS ud1 
INNER JOIN 
    @user_flat_emailtable_dupes AS ud2 
    ON ud1.UserName = ud2.UserName 
WHERE 
     ud2.EmailType = 2  -- Removed sub-query, for layout, doubt it will help performance 
    AND ud2.Email IS NOT NULL 
    AND ud2.Email <> ''  -- Removed the `LEN()` function 

但可能是最重要的过去,以确保您有索引。 JOIN对于这个逻辑(或相关的子查询等)是必要的,所以你想要连接是高性能的。

@user_dupes上的(UserName)的索引以及@user_flat_emailtable_dupes上的(EmailType,Email,UserName)的索引。 (这假定UD2越小表中,过滤后)

随着作为指定的索引,从LEN(Email) > 0Email <> ''的变化可以允许一个索引查找,而不是扫描。你的桌子越大,这就越明显。

+0

用户名上的user_dupes上的唯一索引。以及包含电子邮件类型和电子邮件的用户名上user_flat_emailtable_dupes上的唯一索引。哦,coalesce(ud2.email,'')<>''可以帮助提供的查询一点点。 – jerry 2012-03-23 18:31:03

+0

@jerry - 这不会帮助查询使用索引。通过将该字段包装在一个函数中,可以防止索引查找。优化器解决的两个条件比单个合并条件更容易。 – MatBailie 2012-03-23 21:31:23

+0

如果'ud2.Email <>''',你可以确定它不是NULL。 (这里显式的'IS NOT NULL'测试是不必要的。) – 2012-03-25 03:02:28

1

我相信这个查询会做同样的事情(虽然你必须确保没有重复的用户名形式@user_flat_emailtable_dupes)。我没有检查过他们是否有不同的执行计划。看起来你正在完善垃圾输入,我提到这部分是因为我做了很多,并找到MERGE有用(对我来说更有用,因为我不知道UPDATE FROM的作品)。部分原因是我从未使用过MERGE变量。看来是这样的,至少目标表必须是别名,或者解析器决定@ ud1是一个标量变量,它会中断。

MERGE @user_dupes AS ud1 
USING @user_flat_emailtable_dupes AS ud2 
    ON emailType = 2 
    AND COALESCE(ud2.email, '') <> '' 
    AND ud2.username = ud1.username 
WHEN MATCHED THEN UPDATE 
    SET externalEmail = ud2.email 
    ;