【发布时间】:2018-08-21 04:39:07
【问题描述】:
我正在处理一个查询,我需要转换一个 CSV 值,其中包含几个由, 分隔的 ID。
目前我正在使用取自 here 的表值函数:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[CSVToTable] (@InStr VARCHAR(MAX))
RETURNS @TempTab TABLE
(id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET @InStr = REPLACE(@InStr + ',', ',,', ',')
DECLARE @SP INT
DECLARE @VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', @INSTR ) <> 0
BEGIN
SELECT @SP = PATINDEX('%,%',@INSTR)
SELECT @VALUE = LEFT(@INSTR , @SP - 1)
SELECT @INSTR = STUFF(@INSTR, 1, @SP, '')
INSERT INTO @TempTab(id) VALUES (@VALUE)
END
RETURN
END
GO
我在我的视图中这样使用它:
Select * from SomeTable S where ID in (Select * from CSVtoTable(S.CSVIDs))
现在我已经知道,当对数据集中的大量行(即 > 1000)进行操作时,这将导致性能问题。因为该函数将解析后的数据存储到 Table variable,并且在相同函数的情况下每行调用5次,肯定会出问题。
问题:有没有办法修改代码以获得更好的性能?如果在视图本身中调用相同的内容会更好。
更新:添加示例数据的视觉效果以供参考
我正在运行的 SQL 服务器版本是:
Microsoft SQL Azure (RTM) - 12.0.2000.8
【问题讨论】:
-
通过循环解析数据效率不高。不清楚为什么你每行调用 5 次。也许小样本数据和期望的结果会更有帮助
-
有建议: 1.不要这样存放; 2. 尝试使用新的
string_split函数 3. 第一次加载到表(变量、临时)中并重用表而不是函数 -
@JohnCappelletti,假设实际表中的每一行都有 5 列带有 CSV 值。要为每一列解析它,我们必须调用该函数 5 次。而对于 1000 行的表,该函数将被调用 5000 次。
-
我明白了,我对数学很满意 :) 只是说样本数据的视觉效果可能会促进一种更有效的方法。
-
@JohnCappelletti,很抱歉造成误解 :)。用示例视觉更新了问题。
标签: performance csv tsql azure-sql-database table-variable