2014-02-14 50 views
2

以下過程需要永久。其目的是將ID列表連接成一個字符串。爲什麼連接和聚合的組合很慢?

declare @validatedIDList nvarchar(max) 

SELECT 
    @validatedIDList = COALESCE(@validatedIDList + ', ', '') + CAST(si.SelectedID AS nvarchar(50)) 
FROM 
    dbo.SelectedID si 

dbo.SelectedID是一個只有一個int字段的表。它包含約60000行。我試圖將COALESCE更改爲ISNULL,但沒有明顯的改進。 有關如何更快地提出此請求的任何想法?

+1

這個查詢是否會給你_results_你想要的? –

+0

是的,但比以前花費的時間要長得多:大約10分鐘。 它用於在不同數據庫上使用40000次輸入需要10秒。 – user3240131

+1

重複的字符串連接通常很慢。爲了避免這種情況,.NET有一個'StringBuilder'。 [此方法無法保證無論如何工作](http://stackoverflow.com/questions/15138593/nvarchar-concatenation-index-nvarcharmax-inexplicable-behavior/15163136#15163136) –

回答

2

含有從1 - 60,000連續整數表運行此做把我的機器上剛剛超過5分鐘。

DECLARE @validatedIDList NVARCHAR(max) 

SELECT @validatedIDList = COALESCE(@validatedIDList + ', ', '') + 
          CAST(si.SelectedID AS NVARCHAR(50)) 
FROM dbo.SelectedID si 

SELECT internal_objects_alloc_page_count, 
     internal_objects_dealloc_page_count, 
     internal_objects_alloc_page_count - internal_objects_dealloc_page_count 
FROM sys.dm_db_task_space_usage 
WHERE session_id = @@SPID 


SELECT DATALENGTH(@validatedIDList) 

剖析的過程表明,它花了很多時間進行斑點操縱

enter image description here

要回答這個問題,爲什麼這是如此緩慢nvarchar(max)變量存儲爲LOB數據tempdb上8KB頁面。

字符串的最後長度是817,784字節(大約一百個8KB頁)。上面的查詢的結果是

+-----------------------------------+-------------------------------------+-------+ 
| internal_objects_alloc_page_count | internal_objects_dealloc_page_count |  | 
+-----------------------------------+-------------------------------------+-------+ 
|       5571528 |        5571424 | 104 | 
+-----------------------------------+-------------------------------------+-------+ 

顯示最後一個字符串實際消耗在tempdb 104頁。

alloc_page_count通過60,000除以顯示,分配和每個作業釋放的平均頁數爲93

每個拼接操作不只是追加到現有的LOB數據,而是使得它的一個副本。隨着字符串變長,每個連接的工作量也相應增加。

XML PATH方法更有效地實現,並具有額外的「紅利」,它實際上是記錄工作(unlike the method in the question

文章Concatenating Row Values in Transact-SQL具有良好的一輪上漲的可用方法。

+1

+1,使用'XML PATH'連接值由Microsoft [here](http://technet.microsoft.com/en-us/library/bb510419.aspx)記錄。 –

1

這可以用STUFFFOR XML PATH命令

DECLARE @validatedIDList nvarchar(max) 

SELECT @validatedIDList = STUFF((SELECT ', ' + COALESCE(CAST(si.SelectedID AS (nvarchar(50)), '') 
FROM dbo.SelectedID si 
FOR XML PATH('')), 1, 1, '') 
+0

After – user3240131

+0

啊,我的錯,我把我的查詢從'CONVERT'改爲'CAST',忘記取出paren,很高興收到! – TTeeple

1
DECLARE @SelectedID TABLE (IDs INT) 
INSERT INTO @SelectedID VALUES 
(1),(2),(null),(4),(5),(null),(7) 


declare @validatedIDList nvarchar(max) 


SET @validatedIDList = STUFF((SELECT ', ' + CAST(si.IDs AS nvarchar(50)) 
           FROM @SelectedID si 
           FOR XML PATH('')),1 ,2 ,'') 

SELECT @validatedIDList 


RESULT : 1, 2, 4, 5, 7