2012-03-23 57 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 
    ;