2015-09-16 30 views
1

我想根據uniqueEntries中不存在的actualEntries用戶標識將actualEntries表中的所有記錄插入到uniqueEntries表中。通過一個LEFT JOIN優化SQL子查詢

我從一個包含NOT IN子查詢的SQL子句開始,這個子查詢非常緩慢(在400K記錄上運行時),並將其變爲LEFT JOIN子句,但速度沒有提高。

以下是包含NOT IN子查詢我原來的SQL子句:

INSERT INTO uniqueEntries 
    SELECT * 
    FROM actualEntries 
    WHERE actualEntries.User_ID NOT IN (
    SELECT uniqueEntries.User_ID 
    FROM uniqueEntries 
) 
    GROUP BY User_ID" 

以下是被轉換成後的SQL子句LEFT JOIN

INSERT INTO uniqueEntries 
    SELECT actualEntries.* 
    FROM actualEntries 
    LEFT JOIN uniqueEntries 
    ON uniqueEntries.User_ID = actualEntries.User_ID 
    WHERE uniqueEntries.User_ID IS NULL 
    GROUP BY User_ID 

當我運行50個記錄都querys他們馬上完成,但是當我在400K記錄上運行它們時,它們沒有完成。

完成此操作最快捷的方法是什麼?

UPDATE /溶液: 作爲每@Rahul,@Steve E和@fhthiella我更新了LEFT JOIN如下,並且處理時間減少到2分鐘470K記錄。所有的

INSERT INTO uniqueEntries 
    SELECT actualEntries.* 
    FROM actualEntries 
    LEFT JOIN uniqueEntries 
    ON uniqueEntries.id = actualEntries.id 
    WHERE uniqueEntries.User_ID IS NULL GROUP BY User_ID 

回答

1

首先拆下GROUP BY條款GROUP BY User_ID因爲它並不需要在所有。此外,因爲您正在將它用作聯接列,所以您應該在和actualEntries這兩個表的User_ID列上有一個索引。與此同時,您的查詢應該看起來像

INSERT INTO uniqueEntries 
    SELECT actualEntries.* 
    FROM actualEntries 
    LEFT JOIN uniqueEntries 
    ON uniqueEntries.User_ID = actualEntries.User_ID 
    WHERE uniqueEntries.User_ID IS NULL 
+0

我將uniqueEntries上的.User_ID和actualEntries更改爲.id(即有效)。 我確實需要GROUP BY,因爲有些條目是重複的,我只想要唯一條目 – xited

+0

@xited,但我相信你不需要'GROUP BY'導致where語句'WHERE uniqueEntries.User_ID IS NULL'會做你自己話說。 – Rahul

+0

@Rahul不完全http://sqlfiddle.com/#!9/096ed8/1在這個上下文中,group by仍然是需要的(或者更好地使用主鍵,然後使用INSERT IGNORE http://sqlfiddle.com/ #!9/e3131/1 – fthiella

2

將唯一或主鍵放在uniqueEntries.User_ID上。然後

INSERT IGNORE INTO uniqueEntries 
    SELECT actualEntries.* 
    FROM actualEntries 

IGNORE子句將使MySQL在插入過程中跳過錯誤。 這是the manual說:

如果使用忽略關鍵字,在執行INSERT語句中出現的錯誤 被忽略。對於 示例,如果沒有IGNORE,表中重複索引中的現有UNIQUE 索引或PRIMARY KEY值的行會導致重複鍵錯誤 ,並且語句會中止。使用IGNORE時,該行將被丟棄,並且不會出現 錯誤。忽略的錯誤可能會產生警告,但 重複鍵錯誤不會。

+1

插入忽略幫助我的請求部分。 – xited

1

你應該在兩個uniqueEntries.User_ID和actualEntries.User_ID字段添加一個索引:

ALTER TABLE uniqueEntries ADD INDEX idx_ue_id (User_ID); 
ALTER TABLE actualEntries ADD INDEX idx_ae_id (User_ID); 

,這應使連接速度更快。我也看到,你是選擇所有表字段:

SELECT actualEntries.* 

但隨後你被USER_ID

GROUP BY User_ID 

分組,我認爲你正在做的,因爲有可能是每個USER_ID多行。 MySQL允許你這樣做,但是請注意,如果有多行,你的查詢將只保留一個,但未分組的值將是未定的(它們可以屬於任何分組行)。

+0

@fhthiella重複多行。這是對的,我不在乎哪一個被選中,只要我檢索唯一的行。 – xited

+0

@xited好吧,所以你可以像這樣使用GROUP BY,只要你知道你在做什麼;)但是如果你想讓uniqueEntries的User_ID唯一,我認爲你應該接受steve e answer,因爲它更優雅! – fthiella