У меня есть поле, объявленное как NVARCHAR (MAX), которое я вытаскиваю из таблицы. В большинстве случаев длина составляет менее 1000 символов. Однако поле может содержать некоторый текст HTML, поэтому я использую скалярную функцию, которую я написал, чтобы удалить текст HTML. На действительно длинных строках (например, 600 000 символов) вызов для разметки HTML-текста просто сидит там (я предполагаю, потому что это чертовски много данных для прохождения через скалярную функцию). В конце концов он вернется - примерно через 15 минут, потому что требуется много времени для выполнения скалярного вызова.Самое длинное значение NVARCHAR, переданное скалярной функции
Вот таблица:
CREATE TABLE [dbo].[TextHolder](
[fldClaimTextID] [int] IDENTITY(1,1) NOT NULL,
[fldText] [nvarchar](max) NULL,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Предположим, таблица содержит данные (шахта имеет 250 миллионов строк в нем). 99,99% экземпляров fldText имеют менее 1000 символов.
Так вызов основной функции скалярной работает как шарм 99,99% время, используя следующий запрос:
SELECT
dbo.udf_StripHTML(fldText)
,LEN(fldText) AS fldLength
FROM
TextHolder
Вот выборку данных из 23 записей из моих 250 миллионов или около того, где два результата (строки 8 и 18) являются длинными.
fldLength
285
459
132
141
137
187
129
619182
173
327
433
643
132
141
136
187
129
69
465
428
237
243
178
Итак, мое единственное решение теперь укоротить вызов udf_StripHTML, который является неоптимальным. Далее приведен пример, где я только полоса HTML, когда поле длиной менее 20000 символов):
SELECT
CASE WHEN LEN(fldText) > 20000 THEN fldText ELSE dbo.udf_StripHTML(fldText) END
,LEN(fldText) AS fldLength
FROM
TextHolder
Как я могу передать NVARCHAR, что длиной 600000 символов в скалярной функции без нее занимает много времени.
Боковое замечание. Я работаю на 4-процессорном ящике с 256 ГБ памяти, все выделенное для SQL Server, привязанное к SAN 20 ГБ/с, поэтому у меня нет практических ограничений аппаратного обеспечения.
Я ценю любые мысли. Благодаря!
UPDATE:
Вот функция:
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
* Передача * аргумента скалярной функции вряд ли будет проблемой (хотя, честно говоря, я только передал строковые значения до пары сотен тысяч байтов в SQL Server). Проблема заключается в базовой обработке функции, поэтому вам нужно включить тело функции в вопрос. –
Если функция является шеей бутылки, вы можете попробовать ее оптимизировать. Вы также можете сохранить разделенную версию текста. – Vincent
Кажется, что все в порядке с 200 000 символов. Около 600 000, все получилось плохо. Я думал о сохранении разделенной версии, но общий объем данных составляет около 190 ГБ. –