2016-11-07 64 views
7

我有一個Table Valued Constructor通過其中選擇1 million記錄。它將用於update另一個表。表值構造函數最大行數限制在選擇

SELECT * 
FROM (VALUES (100,200,300), 
       (100,200,300), 
       (100,200,300), 
       (100,200,300), 
       ..... 
       ..... --1 million records 
       (100,200,300)) tc (proj_d, period_sid, val) 

這是我原來的查詢:https://www.dropbox.com/s/ezomt80hsh36gws/TVC.txt?dl=0#

當我做上述select它只是顯示查詢完成有錯誤與顯示任何錯誤消息。

enter image description here

更新:試圖用TRY/CATCH塊捕獲錯誤信息或錯誤號碼,但沒有用的還是同樣的錯誤之前的圖像

BEGIN try 
    SELECT * 
    FROM (VALUES (100,200,300), 
        (100,200,300), 
        (100,200,300), 
        (100,200,300), 
        ..... 
        ..... --1 million records 
        (100,200,300)) tc (proj_d, period_sid, val) 
END try 

BEGIN catch 
    SELECT Error_number(), 
      Error_message() 
END catch 

爲什麼不執行有任何限制用於Select中的Table Valed構造函數。我知道Insert它是1000但我在這裏選擇。

+2

檢查此鏈接:http://stackoverflow.com/questions/14790548/updating-4-million-records-in-sql-server-using-list-of-record-ids-as-input – Laxmi

+0

所有的字面值都需要編譯到執行計劃中。在看到錯誤之前需要多長時間進行編譯? –

+0

@MartinSmith - 總是少於5秒 –

回答

3

有沒有相關的硬編碼限制(65,536 * 4KB的網絡數據包大小爲268 MB,你的劇本長度是遠不及)雖然不宜使用這種方法爲大量的行。

您看到的錯誤是由客戶端工具而不是SQL Server引發的。如果您構建動態SQL編譯SQL字符串能夠至少成功

DECLARE @SQL NVARCHAR(MAX) = '(100,200,300), 
'; 

SELECT @SQL = 'SELECT * FROM (VALUES ' + REPLICATE(@SQL, 1000000) + ' 
(100,200,300)) tc (proj_d, period_sid, val)'; 

SELECT @SQL AS [processing-instruction(x)] 
FOR XML PATH('') 

SELECT DATALENGTH(@SQL)/1048576.0 AS [Length in MB] --30.517705917 

EXEC(@SQL); 

開始雖然我殺了30分鐘以上的編譯時間後〜它仍然沒有產生一行。字面值需要作爲常量表存儲在計劃本身內部,SQL Server花費a lot of time也試圖派生出關於它們的屬性。

SSMS是一個32位應用和拋出一個std::bad_alloc異常而解析所述批次

enter image description here

它試圖的元件推到令牌的載體,其已達到容量和它的企圖調整大小失敗,因爲無法獲得足夠大的連續記憶區域。所以這個說法甚至不會讓它達到服務器。

每次向量容量增長50%(即,遵循the sequence here)。矢量需要增長的能力取決於代碼的佈局方式。

以下需要從19的容量增長到28

SELECT * FROM 
(VALUES 
(100,200,300), 
(100,200,300), 
(100,200,300), 
(100,200,300), 
(100,200,300), 
(100,200,300)) tc (proj_d, period_sid, val) 

和以下只需要一個大小爲2

SELECT * FROM (VALUES (100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300),(100,200,300)) tc (proj_d, period_sid, val) 

以下需要的> 63和<容量= 94。

SELECT * 
FROM (VALUES 
     (100, 
     200, 
     300), 
     (100, 
     200, 
     300), 
     (100, 
     200, 
     300), 
     (100, 
     200, 
     300), 
     (100, 
     200, 
     300), 
     (100, 
     200, 
     300) 
     ) tc (proj_d, period_sid, val) 

對於像情況1那樣佈置的百萬行,向量容量需要增長到3,543,306。

您可能會發現以下任一項都會允許客戶端解析成功。

  1. 減少換行的次數。
  2. 重新啓動SSMS,希望在較少的地址空間碎片時成功請求較大的連續內存。

但是,即使您成功將其發送到服務器,它也只會在執行計劃生成過程中最終導致服務器死機,如上所述。

使用導入導出嚮導加載表格會更好。如果你必須在TSQL中做到這一點,你會發現把它分成更小的批次和/或使用另一種方法比如shreding XML將比表值構造器更好。例如,以下內容在我的機器上以13秒爲單位執行(儘管如果使用SSMS,您仍然可能需要分成多個批次而不是粘貼大量的XML字符串文本)。

DECLARE @S NVARCHAR(MAX) = '<x proj_d="100" period_sid="200" val="300" /> 
' ; 

DECLARE @Xml XML = REPLICATE(@S,1000000); 

SELECT 
    x.value('@proj_d','int'), 
    x.value('@period_sid','int'), 
    x.value('@val','int') 
FROM @Xml.nodes('/x') c(x)