Une de mes questions en mode exécution en série après une sortie et j'ai remarqué que deux nouvelles fonctions ont été utilisées dans une vue référencée dans la requête LINQ vers SQL générée à partir de l'application. J'ai donc converti ces fonctions scalaires aux fonctions TVF, mais la requête est toujours en mode série.
Plus tôt, j'ai fait de la conversion scalaire à TVF dans certaines autres requêtes et elle a résolu le problème de l'exécution de série forcée.
Voici la fonction scalaire:
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
Voici la fonction TVF convertie.
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
Y a-t-il quelque chose de mal à ma mise en œuvre de la fonction TVF qui empêche la requête de fonctionner en mode parallèle.
J'utilise la fonction TVF dans la requête ci-dessous;
select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')
Ma requête réelle qui utilise la vue est assez complexe et si je commencez la partie de fonction dans la vue et sur l'exécution, la requête fonctionne en parallèle.so est la fonction qui oblige la requête à exécuter en parallèle.
Ma requête réelle est dans le format ci-dessous.
select
dv.column1,
dv.column2,
---------
---------
--------
(select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')) AS 'Columnx'
from
DemoView dv
Where
condition1
conditon 2
Toute aide est appréciée.
est-il possible de convertir ma fonction scalaire en TVF en ligne?
Oui. Quelque chose comme le ci-dessous le ferait.
Il est encore assez lourd et si la course corrélée serait probablement assez inefficace. Comme Aaron souligne dans les commentaires, vous l'appelez avec des valeurs constantes, cependant, espérons-le que le plan de requête le reflète et ne le gère qu'une seule fois.
CREATE FUNCTION [dbo].[FindEventReviewDueDateInline] (@EventNumber VARCHAR(20),
@EventID VARCHAR(25),
@EventIDDate BIT)
RETURNS TABLE
AS
RETURN
WITH X
AS (SELECT cis.EventStatus AS CurrentEventStatus,
r.EventDateTime
FROM CurrentEventStatus cis
INNER JOIN Event1 r
ON cis.Event1Id = r.Id
WHERE r.EventNumber = @EventNumber
AND r.EventID = @EventID
AND cis.EventStatus IN ( '0', '6' )
AND @EventIDDate = 1)
SELECT X.CurrentEventStatus,
X.EventDateTime,
CA4.ReviewDueDate
FROM X
--SET @ReviewDueDate = DATEADD(DAY, 30, @EventDateTime)
CROSS APPLY(VALUES(DATEADD(DAY, 30, X.EventDateTime))) CA1(ReviewDueDate)
-- WHILE @ReviewDueDate < getdate()
-- SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
CROSS APPLY(VALUES( IIF(CA1.ReviewDueDate >= GETDATE(), CA1.ReviewDueDate, DATEADD(DAY, 30 * CEILING(( IIF(CAST(GETDATE() AS TIME) > CAST(CA1.ReviewDueDate AS TIME), 1, 0)
+ DATEDIFF(DAY, CA1.ReviewDueDate, GETDATE()) ) / 30.0), CA1.ReviewDueDate)))) CA2(ReviewDueDate)
--SELECT @EventDateJournalDate = ....
CROSS APPLY(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) CA3(EventDateJournalDate)
-- IF(DATEADD(DAY, 30, @EventDateTime) < getdate()
CROSS APPLY(VALUES ( CASE
WHEN ( DATEADD(DAY, 30, X.EventDateTime) < GETDATE()
AND ( CA3.EventDateJournalDate IS NULL
OR DATEADD(DAY, 30, CA3.EventDateJournalDate) < GETDATE() )
AND DATEADD(DAY, 14, CA2.ReviewDueDate) > DATEADD(DAY, 30, GETDATE()) )
THEN DATEADD(DAY, -30, CA2.ReviewDueDate)
WHEN( ( CA3.EventDateJournalDate IS NOT NULL )
AND ( DATEADD(DAY, 30, CA3.EventDateJournalDate) >= CA2.ReviewDueDate ) )
THEN DATEADD(DAY, 30, CA2.ReviewDueDate)
ELSE CA2.ReviewDueDate
END )) CA4(ReviewDueDate);
Forrest est principalement Droite, mais les détails plus fins sont:
SQL Server ne peut pas parlementer des modifications aux variables de table, que votre fonction utilise.
Avant SQL Server 2017's Exécution entrelacée , les estimations de la rangée provenant de fonctions de table de la table multi-instruction étaient très basses.
L'un des effets secondaires est que les plans ont été très médiocres très mal au bas de la fin et ne constitueraient souvent pas le seuil de coût du parallélisme.
SQL Server ne peut pas parlementer des TVF multi-instruction, ce qui est ce que vous êtes. Seuls les TVF en ligne peuvent être paralléliques.