use*_*827 10 performance sql-server parallelism functions query-performance performance-tuning
我的一个查询在发布后以串行执行模式运行,我注意到在从应用程序生成的 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
Run Code Online (Sandbox Code Playgroud)
这是转换后的 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
Run Code Online (Sandbox Code Playgroud)
我的 TVF 函数实现有什么问题吗,阻止查询以并行模式运行。
我在查询中使用 TVF 函数,如下所示;
select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')
Run Code Online (Sandbox Code Playgroud)
我使用视图的实际查询非常复杂,如果我在视图中注释掉函数部分并在执行时,查询并行运行。所以它是强制查询并行运行的函数。
我的实际查询采用以下格式。
select
dv.column1,
dv.column2,
---------
---------
--------
(select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')) AS 'Columnx'
from
DemoView dv
Where
condition1
conditon 2
Run Code Online (Sandbox Code Playgroud)
任何帮助表示赞赏。
是否可以将我的标量函数转换为内联 TVF?
是的。像下面这样的东西会做到这一点。
它仍然相当庞大,如果运行相关,可能效率很低。正如 Aaron 在评论中指出的,您使用常量值调用它,但希望查询计划反映这一点并且只运行一次。
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);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
574 次 |
最近记录: |