[SQL Server] SQL 上的效能議題 - 字串串接
這次也是工作上的遭遇,就順便寫一下 blog 紀錄一下
這次是我在同事的 SQL 上看到了像是
Declare @t NVARCHAR(MAX) = N'' SELECT @t += SerialNo + N',' FROM MyTable
很好,非常的直覺XD ,一看就知道是對 MyTable 上的 SerialNo 欄位作字串串接
那這樣會有什麼問題呢?
其實那樣寫並沒有什麼問題,假設 MyTable 資料量不多的話... XD
可是實務上就是我們 MyTable 高達十幾萬筆,而 SerialNo 則是固定的 20 字元的 NVARCHAR
後來檢視了 SQL,發現他在前面串接,後面又用 split 的 function 將其切割成 Table Variable ,所以我直接使用 Table Variable 裝撈出來指定的 SerialNo (對,上面的 SQL我寫的很簡單,但其實於系統中是有 Where 條件式的),執行時間直接從原本跑起來要四十幾分鐘變成只要1秒鐘,效能差異實在驚人,但這邊的效能差異算是已知的部份,而這次主題我還是想研究字串串接的部份,畢竟難免會有這樣的需求,那該如何才能產出一個有效率的字串串接結果呢?
此時我就想到了前一陣子我很愛用的串接語法... FOR XML PATH('')
不試不知道,一試嚇死人,使用 FOR XML PATH('') ,在一樣的資料集下,其最後的結果只花 2 秒, 2sec VS 40min ,FOR XML PATH 完勝呀!
所以在字串串接上,推薦的串接法還是使用 XML PATH('') , 儘可能的不要使用像原本的 @t 變數的連結串接。
另外延伸閱讀是網路上找到的有趣的比較資料,他是用 CTE vs FOR XML PATH(''),有興趣的可以看看!
Reference:
[1] http://blog.darkthread.net/post-2016-01-21-col-merge-benchmark.aspx
那這樣會有什麼問題呢?
其實那樣寫並沒有什麼問題,假設 MyTable 資料量不多的話... XD
可是實務上就是我們 MyTable 高達十幾萬筆,而 SerialNo 則是固定的 20 字元的 NVARCHAR
後來檢視了 SQL,發現他在前面串接,後面又用 split 的 function 將其切割成 Table Variable ,所以我直接使用 Table Variable 裝撈出來指定的 SerialNo (對,上面的 SQL我寫的很簡單,但其實於系統中是有 Where 條件式的),執行時間直接從原本跑起來要四十幾分鐘變成只要1秒鐘,效能差異實在驚人,但這邊的效能差異算是已知的部份,而這次主題我還是想研究字串串接的部份,畢竟難免會有這樣的需求,那該如何才能產出一個有效率的字串串接結果呢?
此時我就想到了前一陣子我很愛用的串接語法... FOR XML PATH('')
Declare @t NVARCHAR(MAX) = N'' SET @t = (SELECT SerialNo + N',' FROM MyTable FOR XML PATH(''))
不試不知道,一試嚇死人,使用 FOR XML PATH('') ,在一樣的資料集下,其最後的結果只花 2 秒, 2sec VS 40min ,FOR XML PATH 完勝呀!
所以在字串串接上,推薦的串接法還是使用 XML PATH('') , 儘可能的不要使用像原本的 @t 變數的連結串接。
另外延伸閱讀是網路上找到的有趣的比較資料,他是用 CTE vs FOR XML PATH(''),有興趣的可以看看!
Reference:
[1] http://blog.darkthread.net/post-2016-01-21-col-merge-benchmark.aspx
留言
張貼留言