Один из моих запросов был запущен в режиме последовательного выполнения после выпуска, и я заметил, что в представлении, на которое ссылаются в запросе LINQ to SQL, созданном из приложения, были использованы две новые функции. Поэтому я преобразовал эти функции SCALAR в функции TVF, но запрос все еще выполняется в последовательном режиме.
Ранее я выполнял преобразование Scalar в TVF в некоторых других запросах, и это решило проблему принудительного последовательного выполнения.
Вот скалярная функция:
CREATE FUNCTION [dbo].[FindEventReviewDueDate]
(
@EventNumber VARCHAR(20),
@EventID VARCHAR(25),
@EventIDDate BIT
)
RETURNS DateTime
AS
BEGIN
DECLARE @CurrentEventStatus VARCHAR(20)
DECLARE @EventDateTime DateTime
DECLARE @ReviewDueDate DateTime
SELECT @CurrentEventStatus = (SELECT cis.EventStatus
FROM CurrentEventStatus cis
INNER JOIN Event1 r WITH (NOLOCK) ON (cis.Event1Id = r.Id)
WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)
SELECT @EventDateTime = (SELECT EventDateTime FROM Event1 r
WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)
IF @CurrentEventStatus IN ('0','6') AND EventIDDate = 1
BEGIN
SET @ReviewDueDate = DATEADD(DAY, 30, @EventDateTime)
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
DECLARE @EventDateJournalDate DateTime
SELECT @EventDateJournalDate = (SELECT TOP 1 ij.Date
FROM EventPage_EventJournal ij
INNER JOIN EventJournalPages p ON ij.PageId = p.Id
INNER JOIN Journal f ON p.FormId = f.Id
INNER JOIN Event1 r WITH (NOLOCK) ON (f.Event1Id = r.Id)
WHERE (r.EventNumber = @EventNumber AND r.EventID = @EventID) AND ij.ReviewType = 'Supervisor Monthly Review' ORDER BY ij.Date DESC)
IF(DATEADD(DAY, 30, @EventDateTime) < getdate() AND
(@EventDateJournalDate is null OR DATEADD(DAY, 30, @EventDateJournalDate) < getdate()) AND
DATEADD(DAY, 14, @ReviewDueDate) > DATEADD(DAY, 30, getdate()))
SET @ReviewDueDate = DATEADD(DAY, -30, @ReviewDueDate)
ELSE IF((@EventDateJournalDate is not null ) AND (DATEADD(DAY, 30, @EventDateJournalDate) >= @ReviewDueDate))
SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
END
RETURN @ReviewDueDate
END
Вот преобразованная функция TVF.
CREATE FUNCTION [dbo].[FindEventReviewDueDate_test]
(
@EventNumber VARCHAR(20),
@EventID VARCHAR(25),
@EventIDDate BIT
)
RETURNS @FunctionResultTableVairable TABLE (
CurrentEventStatus varchar(20),
Event1DateTime DateTime,
ReviewDueDate DateTime
)
AS
BEGIN
DECLARE @CurrentEventStatus VARCHAR(20)
DECLARE @EventDateTime DateTime
DECLARE @ReviewDueDate DateTime
SELECT @CurrentEventStatus = (SELECT cis.EventStatus
FROM CurrentEventStatus cis
INNER JOIN Event1 r WITH (NOLOCK) ON (cis.Event1Id = r.Id)
WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)
SELECT @EventDateTime = (SELECT EventDateTime FROM Event1 r
WHERE (r.EventNumber = @EventNumber) AND r.EventID = @EventID)
IF @CurrentEventStatus IN ('0','6') AND EventIDDate = 1
BEGIN
SET @ReviewDueDate = DATEADD(DAY, 30, @EventDateTime)
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
DECLARE @EventDateJournalDate DateTime
SELECT @EventDateJournalDate = (SELECT TOP 1 ij.Date
FROM EventPage_EventJournal ij
INNER JOIN EventJournalPages p ON ij.PageId = p.Id
INNER JOIN Journal f ON p.FormId = f.Id
INNER JOIN Event1 r WITH (NOLOCK) ON (f.Event1Id = r.Id)
WHERE (r.EventNumber = @EventNumber AND r.EventID = @EventID) AND ij.ReviewType = 'Supervisor Monthly Review' ORDER BY ij.Date DESC)
IF(DATEADD(DAY, 30, @EventDateTime) < getdate() AND
(@EventDateJournalDate is null OR DATEADD(DAY, 30, @EventDateJournalDate) < getdate()) AND
DATEADD(DAY, 14, @ReviewDueDate) > DATEADD(DAY, 30, getdate()))
SET @ReviewDueDate = DATEADD(DAY, -30, @ReviewDueDate)
ELSE IF((@EventDateJournalDate is not null ) AND (DATEADD(DAY, 30, @EventDateJournalDate) >= @ReviewDueDate))
SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
insert into @FunctionResultTableVairable
select @CurrentEventStatus,@EventDateTime,@ReviewDueDate
END
return;
END
GO
Что-то не так с моей реализацией функции TVF, которая препятствует выполнению запроса в параллельном режиме.
Я использую функцию TVF в запросе, как показано ниже;
select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')
Мой фактический запрос, использующий представление, является довольно сложным, и если я закомментирую часть функции в представлении и при выполнении, запрос выполняется параллельно. Так что это функция, которая заставляет запрос выполняться параллельно.
Мой фактический запрос в следующем формате.
select
dv.column1,
dv.column2,
---------
---------
--------
(select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')) AS 'Columnx'
from
DemoView dv
Where
condition1
conditon 2
Любая помощь приветствуется.
Ответы:
Да. Нечто подобное ниже сделало бы это.
Это все еще довольно здоровенный, и если запустить коррелированные, скорее всего, будет неэффективно. Как указывает Аарон в комментариях, вы называете это с постоянными значениями, хотя, надеюсь, план запроса отражает это и запускает его только один раз.
источник
Форрест в основном прав, но более тонкие детали:
SQL Server не может распараллеливать модификации переменных таблицы, которые использует ваша функция.
До выполнения чередованного выполнения в SQL Server 2017 оценки строк из многозначных табличных функций были очень низкими.
Одним из побочных эффектов этого является то, что планы на низком уровне очень плохо стоили, и часто не нарушали порог стоимости для параллелизма.
источник
SQL Server не может распараллеливать TVF с несколькими операторами, что является вашим. Только встроенные TVF могут быть распараллелены.
источник