Eine meiner Abfragen in wurde nach einer Veröffentlichung im seriellen Ausführungsmodus ausgeführt, und ich stellte fest, dass zwei neue Funktionen in einer Ansicht verwendet wurden, auf die in der von der Anwendung generierten LINQ to SQL-Abfrage verwiesen wird. Also habe ich diese SCALAR-Funktionen in TVF-Funktionen konvertiert, aber die Abfrage wird immer noch im seriellen Modus ausgeführt.
Früher habe ich in einigen anderen Abfragen die Konvertierung von Scalar in TVF durchgeführt und das Problem der erzwungenen seriellen Ausführung gelöst.
Hier ist die Skalarfunktion:
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
Hier ist die konvertierte TVF-Funktion.
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
Stimmt etwas mit meiner Implementierung der TVF-Funktion nicht, die verhindert, dass die Abfrage im parallelen Modus ausgeführt wird?
Ich benutze die TVF-Funktion in der Abfrage wie folgt;
select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')
Meine eigentliche Abfrage, die die Ansicht verwendet, ist ziemlich komplex, und wenn ich den Funktionsteil in der Ansicht und beim Ausführen auskommentiere, wird die Abfrage parallel ausgeführt. Es ist also die Funktion, die die Abfrage dazu zwingt, parallel ausgeführt zu werden.
Meine eigentliche Anfrage ist im folgenden Format.
select
dv.column1,
dv.column2,
---------
---------
--------
(select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')) AS 'Columnx'
from
DemoView dv
Where
condition1
conditon 2
Jede Hilfe wird geschätzt.
Antworten:
Ja. So etwas wie das Folgende würde es tun.
Es ist immer noch ziemlich heftig und wenn der Lauf korreliert wäre, wäre es wahrscheinlich ziemlich ineffizient. Wie Aaron in den Kommentaren hervorhebt, rufen Sie dies mit konstanten Werten auf. Hoffentlich spiegelt der Abfrageplan dies wider und führt ihn nur einmal aus.
quelle
Forrest hat größtenteils recht, aber die feineren Details sind:
SQL Server kann Änderungen an Tabellenvariablen, die Ihre Funktion verwendet, nicht parallelisieren.
Vor der Interleaved Execution von SQL Server 2017 waren die Zeilenschätzungen aus Funktionen mit Tabellenwerten für mehrere Anweisungen sehr niedrig.
Ein Nebeneffekt davon ist, dass Pläne im unteren Bereich sehr schlecht bewertet wurden und häufig die Kostenschwelle für Parallelität nicht überschreiten.
quelle
SQL Server kann TVFs mit mehreren Anweisungen nicht parallelisieren. Es können nur Inline-TVFs parallelisiert werden.
quelle