1. 程式人生 > >SQL SERVER中使用Merge進行批量操作

SQL SERVER中使用Merge進行批量操作

在.net開發過程中,經常會和資料庫打交道。微軟的產品包裡,SQL SERVER便是一個強大的資料庫管理系統(DBS)。我們編寫的.net程式怎麼和DBS進行互動呢?筆者最常用的便是ado.net元件,其中包括了執行sql命令,執行儲存過程等豐富的操作方法。在ERP(企業資源計劃)系統中,最常見的場景便是單條資料的增、刪、改,或者小批量的DML(資料操縱語言)操作。在這種場景下,應用程式和DBS的互動延遲是很少被關注的(注意:ERP系統中的查詢效率往往是開發過程中的優化重點)。但是,在一個頻繁執行DML操作的系統中,互動延遲就成為了影響整體效能的一個關鍵點。

比如,某個處理過程接收一個體積較大的輸入,經過內部邏輯運算後,產出幾個體積較大的輸出,最後要將輸出結果儲存到資料庫中。假設完成一條Insert命令需要10ms,200條資料就需要2s,2000條資料就需要20s。如果程式中其他功能的執行時間總和為5s,那麼此處的20s就是個禍害。怎樣縮短這個時間呢?.net裡提供了SqlBulkCopy型別,支援將一個數據集以批量的方式快速插入到資料庫中。20s可以變成200ms,效果是明顯的,侷限也是明顯的。純插入操作場景是很少的,插入和更新並行場景是更加常見的。這時我們就會希望.net,或者DBS為我們提供一個“無則插入,有則更新”的功能。

MySQL資料庫管理系統就提供了這個實用的功能,不過SQL SERVER中沒有這個功能,那怎麼辦呢?

一條道走到黑不行了,我們可以曲線救國。SQL SERVER 2008中添加了Merge關鍵字,其詳細語法此處不再列出,功能就是對兩張表進行合併操作。我們可以指定匹配規則,兩條記錄匹配的時候可以定義更新或者刪除操作,不匹配時定義插入或者刪除操作。仔細一想,這就包含了“無則插入,有則更新”。接下來就是具體如何實現了。

筆者的實現思路如下:在應用程式中,將結果集快取起來,然後使用SqlBulkCopy批量插入到一張副表,接下來呼叫儲存過程執行Merge操作將副表資料合併到主表,最後清空副表。兩個過程的速度都是很快的,所以整體效能也很可觀。唯一麻煩的就是,必須為目標表建立一張副表。不過副表會被不斷清空,不佔用儲存空間,所以還是值得使用的。

Merge的語法層面的限制較多,筆者研究的不是很深入,歡迎發表不同觀點。