我每天都在下载一个大文件。到目前为止,我的.NET程序已经在后台线程中处理了它;但是,我们偶尔会遇到有人在完成之前重新启动的问题,并且必须重新开始。
我正在尝试将其迁移到SQL Server。我可以非常快速地将整个文件转储为varchar(max)。这个想法是在写入行后在SQL Server中触发长时间运行的操作。
然而,它永远不会回来。我的猜测最终会是这样,因为我的分裂功能经过了很好的测试并且我已经使用了很多年,但是我已经等了7分钟,即使我从循环中抽象它并且仅在第一行操作。我从来没有得到第一排。
必须有另一种方法来操作大数据,这些数据在拥有数十万行的内容中每行不会花费10分钟。
我查看了STRING_SPLIT,但不幸的是我们在2012年才开始使用它。
我的分割功能(原始代码来自这里。它适用于较小的varchars)。
ALTER FUNCTION [dbo].[fnSplitReturnVarchar](
@sInputList VARCHAR(max) -- List of delimited items
, @sDelimiter VARCHAR(10) = ',' -- delimiter that separates items
) RETURNS @List TABLE (rowNum int identity,item VARCHAR(max))
BEGIN
DECLARE @sItem VARCHAR(max)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
BEGIN
SELECT
@sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX( @sDelimiter,@sInputList,0)-1))),
@sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter, @sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))
IF LEN(@sItem) > 0
INSERT INTO @List SELECT @sItem
END
IF LEN(@sInputList) > 0
INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END
同样,这适用于小字符串。例如:
SELECT * FROM dbo.fnSplitReturnVarchar('12#45','#')
返回
rowNum item
1 12
2 45
但是,此varchar的LEN(@String)是2,379,052。 我在char(10)上拆分,最后需要在逗号上拆分 - 但我甚至无法将char(10)拆分回来。
例如:
DECLARE @YesterdayFullStringFut varchar(max) = (SELECT DataString
FROM CMESettleStaging
WHERE [Date] = CAST(DATEADD(DAY,-1,GETDATE()) AS date)
AND DataType = 'Future')
SELECT LEN(@YesterdayFullStringFut) --2379052
DECLARE @ProcessLine varchar(max) = (SELECT item
FROM dbo.fnSplitReturnVarchar(@YesterdayFullStringFut,char(10))
WHERE rowNum = 2) --never returns, 8:30 longest wait - too long.
SELECT @ProcessLine
如何使用大数据执行此操作?它花了很长时间在.NET中,但并非在任何地方接近这个长期。
答案 0 :(得分:0)
使用2016内置的STRING_SPLIT,我们获得了非常好的性能。我们在本地使用2012,但已经将Azure设置为140 compat(2017),其中包括STRING_SPLIT。所以,我写了下面的内容,我们从几个小时的处理(在.NET中最快是82分钟)到大约45秒完全在SQL中。
DECLARE @Results TABLE([1] varchar(50), [2] varchar(50), [3] varchar(50), [4] varchar(50), [5] varchar(50),[6] varchar(250), [7] varchar(50), [8] varchar(50), [9] varchar(50), [10] varchar(50),
[11] varchar(50), [12] varchar(50), [13] varchar(50), [14] varchar(50), [15] varchar(50),[16] varchar(50), [17] varchar(50), [18] varchar(50), [19] varchar(50), [20] varchar(50),
[21] varchar(50), [22] varchar(50))
--@Results to perm table.
DECLARE @Temp TABLE ([value] varchar(max))
INSERT INTO @Temp
SELECT [value] FROM STRING_SPLIT(@data,char(10))
DECLARE @innerData varchar(100)
DECLARE cur CURSOR FOR
SELECT [value] FROM @Temp
OPEN cur
FETCH NEXT FROM cur
INTO @innerData;
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @Results
SELECT p2.[1],p2.[2],p2.[3],p2.[4],p2.[5],p2.[6],p2.[7],p2.[8],p2.[9],p2.[10],
p2.[11],p2.[12],p2.[13],p2.[14],p2.[15],p2.[16],p2.[17],p2.[18],p2.[19],p2.[20],
p2.[21],p2.[22]
FROM(
SELECT ROW_NUMBER() OVER(Order BY @innerData) AS rowNum,* FROM STRING_SPLIT(@innerData,',')
) p
PIVOT
(
MAX([value])
FOR rowNum IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],
[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],
[21],[22])
) p2
FETCH NEXT FROM cur INTO @innerData;
END
SELECT * FROM @Results
这在47秒内处理了24,039行,这是一项重大改进,对我们来说效果很好。