在 SQL Server 中插入一定數量的列後性能下降
我正在開發一個應用程序,它具有將表格數據導出到指定數據庫表的功能。該應用程序使用
INSERT
語句將其數據導出到目標數據庫。插入是通過一個批處理
INSERT
語句完成的,每個 SQLINSERT
語句有 100 行(現在我不能使用BULK INSERT
orbcp
)。我注意到,當源數據中的列數超過某個數字時,導出時間會不成比例地增加(該數字不是固定的,取決於值的大小、每個值的行數
INSERT
等等)。例如,導出 50 000 行(500 條
INSERT
語句,每條 100 行)隨機字元串,每行 100 個字元,每次 100 行INSERT
:3 秒,5 列 6 秒,10 列 56 秒,15 列 77 秒,20 列
請注意 10 和 15 列之間的導出時間差異。我原以為 15 列的導出時間為 9-10 秒,但實際上要長 5 倍。在測試其他數據集的導出時,我能夠發現類似的性能下降。
為了確保問題不在我這邊,我
INSERT
通過sqlcmd.exe
. 我得到了類似的結果。**問題:**如何使 SQL Server 處理大量列的速度與處理小列一樣快?或者至少將性能下降點“移動”到更多列?
額外細節:
INSERT
查詢在本地 SQL Server Express 2014(64 位)版本 12.0.5000.0 上執行;- 數據庫恢復模式設置為簡單;
- 所有
INSERT
語句都包裝在一個事務中(我嘗試COMMIT
在每個事務之後呼叫INSERT
,但結果幾乎相同);- 目標表是在每次測試之前創建的。這是一個沒有任何索引、外鍵、約束等的簡單表;
- 硬碟驅動器性能似乎不是問題的根源,因為在前兩個測試(5 列和 10 列)中,磁碟寫入速度是後兩個測試的
sqlservr.exe
10 倍。表是這樣創建的:
CREATE TABLE [Test_Table] ( [Column 1] VARCHAR(255), [Column 2] VARCHAR(255), [Column 3] VARCHAR(255), [Column 4] VARCHAR(255), [Column 5] VARCHAR(255) )
數據看起來像這樣(每個單元格實際上包含 100 個字元長的字元串,同一行中的所有字元串都相等):
+------------+------------+------------+------------+------------+ | [第 1 欄] | [第 2 欄] | [第 3 欄] | [第 4 欄] | [第 5 欄] | +------------+------------+------------+------------+------------+ | R6YZ..uWaQ | R6YZ..uWaQ | R6YZ..uWaQ | R6YZ..uWaQ | R6YZ..uWaQ | | DMNW..Kh0a | DMNW..Kh0a | DMNW..Kh0a | DMNW..Kh0a | DMNW..Kh0a | | GKbg..yuap | GKbg..yuap | GKbg..yuap | GKbg..yuap | GKbg..yuap | | pG+f..64bX | pG+f..64bX | pG+f..64bX | pG+f..64bX | pG+f..64bX | | O2Q7..fTNF | O2Q7..fTNF | O2Q7..fTNF | O2Q7..fTNF | O2Q7..fTNF |
以下是重現該問題的兩個範例:
http://rextester.com/OZI56670(10列,~0.09 秒)
http://rextester.com/HLAP4972(11列,~0.45 秒)
您發布的 10 列和 100 行與 11 列和 100 行的複制之間的區別在於第一個的執行計劃使用Simple Parameterization。
10 列的實際執行計劃列出了從
@1
到的參數@1000
。
11 * 100
是1100
。但是一千似乎是自動參數化查詢可以達到的最大參數數量。您正在為每個插入 10 次。在 10 列的情況下,計劃可以編譯一次,然後再用於其他 9 個插入。在 11 列的情況下,每個插入語句都需要單獨編譯。
此外,當 SQL Server 需要查看文字值時,編譯過程需要更長的時間,因為它會花時間計算組的屬性(或者至少以前是這種情況,我不確定這在最近的版本中是否發生了變化)。