我有一个声明为NVARCHAR(MAX)的字段,我从表中提取。在大多数情况下,长度小于1,000个字符。但是,该字段可以包含一些HTML文本,因此我使用我编写的标量函数来删除HTML文本。在非常长的字符串(例如,600,000个字符)上,剥离HTML文本的调用就在那里(我假设因为这是通过标量函数传递的大量数据)。它将最终返回 - 大约15分钟后,因为需要很长时间才能进行标量调用。
这是表:
CREATE TABLE [dbo].[TextHolder](
[fldClaimTextID] [int] IDENTITY(1,1) NOT NULL,
[fldText] [nvarchar](max) NULL,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
假设该表有数据(我的数据有2.5亿行)。 99.99%的fldText实例少于1,000个字符。
因此,使用以下查询,对99,000%的基本标量函数的调用就像魅力一样:
SELECT
dbo.udf_StripHTML(fldText)
,LEN(fldText) AS fldLength
FROM
TextHolder
以下是我的2.5亿左右记录中23条记录的数据样本,其中两条结果(第8行和第18行)很长。
fldLength
285
459
132
141
137
187
129
619182
173
327
433
643
132
141
136
187
129
690123
465
428
237
243
178
所以,我现在唯一的解决方案是截断对udf_StripHTML的调用,这是次优的。请参阅下面的示例,其中我只在字段长度少于20,000个字符时删除HTML):
SELECT
CASE WHEN LEN(fldText) > 20000 THEN fldText ELSE dbo.udf_StripHTML(fldText) END
,LEN(fldText) AS fldLength
FROM
TextHolder
如何在不花费很长时间的情况下将600,000个字符长的nvarchar传递给标量函数。
旁注,我正在使用256GB内存的4处理器盒上运行,全部专用于SQL Server,绑定在20GB / s SAN上,因此我没有实际的硬件限制。
我很感激任何想法。谢谢!
更新:
这是功能:
ALTER FUNCTION [dbo].[udf_StripHTML]
(
@HTMLText varchar(MAX)
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE @Start int
DECLARE @End int
DECLARE @strippedString nvarchar(MAX) = N''
DECLARE @currentChar nvarchar
DECLARE @ignoreCharacter bit = 0
-- Replace any <br> tags with a newline characters
SET @Start = 0
SET @End = LEN(@HTMLText)
-- This is an incremental algorithm that traverses the string only once, which means that it should be fast. It basically starts at the 0th character, going through
-- the entire string. When it finds a starting "<", it sets a flag to ignore all characters until it finds a closing ">" (if it never finds one, it truncates the rest
-- of the string. We only add characters to the return string when the ignore flag is turned off.
WHILE @Start < @End
BEGIN
SET @currentChar = SUBSTRING(@HTMLText,@Start,1)
-- Found a starting bracket, so turn on the ignore flag
IF @currentChar = N'<'
SET @ignoreCharacter = 1
-- Found an ending bracket, so turn off the ignore flag
ELSE IF @currentChar = N'>'
SET @ignoreCharacter = 0
ELSE
-- If we have a non-bracket character and the ignore flag is off, then add the character to our return value
IF @ignoreCharacter = 0
SET @strippedString = @strippedString + @currentChar
SET @Start = @Start + 1
END
RETURN @strippedString
END