最近在處理大數據量導入的時候,使用OPENROWSET將Excel導入到臨時表中之后,需要對數據進行唯一性驗證。這時候發現使用NOT IN嚴重影響效率,一條sql可能執行10分鍾甚至更久。嘗試改變寫法提供效率。關於OPENROWSET可以查看連接http://www.cnblogs.com/diaoyan/p/5822631.html
現在有表 tbl_crm_accountprospect,字段 col_id,col_name,col_status,數據量是7萬條。
首先明確要編寫的sql的需求,我需要的是得到一個結果集,里面沒有重復的數據,通過col_name列判斷是否重復,主鍵是col_id。
這樣得到sql:
SELECT MIN(col_id) FROM tbl_crm_accountprospect GROUP BY col_name
這樣相同的col_name第二次出現的時候,就當作是重復數據。
由於程序需要,我要把重復數據,也就是除了上面之外的數據的狀態col_status修改為1。首先想到的就是使用NOT IN,得到下面sql:
UPDATE tbl SET tbl.col_status= 1 FROM tbl_crm_accountprospect AS tbl
WHERE tbl.col_id NOT IN (SELECT MIN(col_id) FROM tbl_crm_accountprospect GROUP BY col_name)
執行這個sql花了1283.617秒,20分鍾多。這個效率是不可接受的,而且現在數據量僅僅是7萬,如果數據量達到百萬之后,這個sql是完全沒有意義的。
開始找替代方案:
UPDATE tbl_a SET tbl_a.col_status = 1 FROM tbl_crm_accountprospect AS tbl_a
LEFT JOIN (SELECT MIN(col_id) AS col_id FROM tbl_crm_accountprospect GROUP BY col_name) AS tbl_b ON tbl_a.col_id = tbl_b.col_id
WHERE tbl_b.col_id IS NULL
執行這個sql花了0.147秒受影響行數是19084。
可以通過left join 關聯子查詢在判斷關聯列為空來實現NOT IN 的功能。