У меня есть запрос, который занимает около 3 часов на нашем сервере - и он не использует преимущества параллельной обработки. (около 1,15 миллионов записей в dbo.Deidentified
, 300 записей в dbo.NamesMultiWord
). Сервер имеет доступ к 8 ядрам.
UPDATE dbo.Deidentified
WITH (TABLOCK)
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml),
DE461 = dbo.ReplaceMultiWord(DE461),
DE87 = dbo.ReplaceMultiWord(DE87),
DE15 = dbo.ReplaceMultiWord(DE15)
WHERE InProcess = 1;
и ReplaceMultiword
это процедура, определенная как:
SELECT @body = REPLACE(@body,Names,Replacement)
FROM dbo.NamesMultiWord
ORDER BY [WordLength] DESC
RETURN @body --NVARCHAR(MAX)
Является ли призыв к ReplaceMultiword
предотвращению формирования параллельного плана? Есть ли способ переписать это, чтобы позволить параллелизм?
ReplaceMultiword
работает в порядке убывания, потому что некоторые замены являются короткими версиями других, и я хочу, чтобы самое длинное совпадение было успешным.
Например, может быть «Университет Джорджа Вашингтона» и другой из «Университета Вашингтона». Если бы матч «Вашингтонского университета» был первым, то «Джордж» остался бы позади.
Технически я могу использовать CLR, я просто не знаю, как это сделать.
SELECT @var = REPLACE ... ORDER BY
Конструкция не гарантирует работу , как вы ожидаете. Пример подключения элемента (см. Ответ от Microsoft). Таким образом, переход на SQLCLR имеет дополнительное преимущество, гарантирующее правильные результаты, что всегда приятно.Ответы:
UDF предотвращает параллелизм. Это также вызывает эту катушку.
Вы можете использовать CLR и скомпилированное регулярное выражение для поиска и замены. Он не блокирует параллелизм, пока присутствуют обязательные атрибуты, и, вероятно, будет значительно быстрее, чем выполнение 300
REPLACE
операций TSQL за вызов функции.Пример кода ниже.
Это зависит от наличия UDF CLR, как показано ниже (это
DataAccessKind.None
должно означать, что катушка исчезает, так же как и для защиты Хэллоуина и не нужна, так как она не обращается к целевой таблице).источник
where
предложения, используя тест на совпадение с регулярным выражением, так как большинство записей не нужны - плотность «попаданий» должна быть низкой, но мои навыки C # (я парень C ++) не доставь меня туда. Я думал о процедуреpublic static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
, которая возвращала бы,return Regex.IsMatch(inputString.ToString());
но я получаю ошибки в этом операторе возврата, например, `System.Text.RegularExpressions.Regex является типом, но используется как переменная.Итог : добавление критериев к
WHERE
предложению и разделение запроса на четыре отдельных запроса, по одному для каждого поля, позволило SQL-серверу предоставить параллельный план и ускорить выполнение запроса в 4 раза, как это было без дополнительного теста вWHERE
предложении. Разделение запросов на четыре без теста не сделало этого. Ни один не сделал добавление теста без разделения запросов. Оптимизация теста сократила общее время выполнения до 3 минут (с первоначальных 3 часов).Моему исходному UDF потребовалось 3 часа 16 минут, чтобы обработать 1 174 731 строку, при этом было протестировано 1,216 ГБ данных nvarchar. Используя CLR, предоставленный Мартином Смитом в его ответе, план выполнения все еще не был параллельным, и задача заняла 3 часа и 5 минут.
Прочитав, что
WHERE
критерии могут помочь подтолкнутьUPDATE
к параллели, я сделал следующее. Я добавил функцию в модуль CLR, чтобы увидеть, соответствует ли поле регулярному выражению:и, в
internal class ReplaceSpecification
, я добавил код для выполнения теста с регулярным выражениемЕсли все поля проверены в одном операторе, SQL-сервер не распараллеливает работу
Время выполнения более 4,5 часов и все еще работает. План выполнения:
Однако, если поля разделены на отдельные операторы, используется параллельный рабочий план, и моя загрузка ЦП увеличивается с 12% для последовательных планов до 100% для параллельных планов (8 ядер).
Время выполнения 46 минут. Статистика строк показала, что около 0,5% записей имели хотя бы одно совпадение с регулярным выражением. План выполнения:
Теперь основным моментом затягивания был
WHERE
пункт. Затем я заменил критерий регулярного выражения вWHERE
предложении алгоритмом Aho-Corasick, реализованным в виде CLR. Это уменьшило общее время до 3 минут 6 секунд.Это потребовало следующих изменений. Загрузите сборку и функции для алгоритма Aho-Corasick. Изменить
WHERE
пункт наИ добавить следующее перед первым
UPDATE
источник