DROP & CREATE FUNCTION улучшенная производительность - PullRequest
0 голосов
/ 24 августа 2018

У меня есть запрос, который использовал табличную функцию с несколькими утверждениями в предложении WHERE, как таковое:

WHERE value IN (SELECT * FROM dbo.Split('SO',','))

Возвращаемым значением функции является таблица с одной ячейкой, 'SO'

Я обнаружил, что запрос выполняется намного быстрее без функции:

WHERE value = 'SO'
WHERE value IN ('SO')
WHERE value IN (SELECT 'SO')

В конце концов я удалил и создал функцию, не меняя код, и запрос выполнялся намного быстрее. Раньше это не завершалось за минуту, а теперь это занимает секунду.

Что могло измениться, когда я сбросил и заново создал функцию?

Ответы [ 3 ]

0 голосов
/ 24 августа 2018

Это слишком долго для комментария.

SQL Server компилирует запросы в хранимых функциях и хранимых процедурах при первом вызове.Решения, принятые оптимизатором, основаны на статистике и параметрах таблицы в то время.

Это называется анализ параметров (я не фанат этого термина, потому что решенияоснованный как на параметрах, так и на статистике таблиц).

Ваш опыт показывает, что план запроса был неоптимальным - обычно это было бы различием между соединением на основе хеш-функции и соединением с вложенным циклом.Иногда это можно исправить с помощью индекса.

Другим распространенным исправлением является принудительная перекомпиляция запроса (или запросов) в программном коде.Однако это приводит к накладным расходам перекомпиляции.Такие издержки должны быть небольшими для запроса, выполнение которого занимает минуту, но более значимы, если запрос занимает менее секунды.

0 голосов
/ 24 августа 2018

Пожалуйста, попробуйте использовать Tally Tables вместо UDF и дайте мне знать.

declare @mytbl table (Value varchar(100))
insert into @mytbl values('Element01'),('Element04')

DECLARE @Parameter VARCHAR(8000)
    SET @Parameter = ',Element01,'

IF OBJECT_ID('dbo.tally') is not null
drop table dbo.tally

select TOP (select len(@Parameter)) identity(INT,1,1) AS N INTO TALLY FROM Master.dbo.SysColumns sc1,Master.dbo.SysColumns  c2

select * from @mytbl **where Value in (SELECT sUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,n+1)-n-1)
   FROM dbo.Tally
  WHERE N <= LEN(@Parameter)-1
    AND SUBSTRING(@Parameter,N,1) = ','
  )**

Спасибо

0 голосов
/ 24 августа 2018

Я бы использовал CROSS APPLY вместо IN предложения:

SELECT t.*
FROM table t CROSS APPLY
    (SELECT * FROM dbo.Split('SO',',') 
    ) tt
WHERE t.value = tt.col;

Если у вас есть string с большим no_sos, то предложение IN приведет к снижению производительности.

...