Đã chuyển đổi chức năng Vô hướng thành chức năng TVF để thực hiện song song - Vẫn đang chạy ở chế độ Nối tiếp


10

Một trong những truy vấn của tôi đang chạy trong chế độ thực thi nối tiếp sau khi phát hành và tôi nhận thấy rằng hai hàm mới đã được sử dụng trong chế độ xem được tham chiếu trong Truy vấn LINQ to SQL được tạo từ ứng dụng. Vì vậy, tôi đã chuyển đổi các hàm SCALAR đó thành các hàm TVF, nhưng truy vấn vẫn đang chạy ở chế độ nối tiếp.

Trước đó tôi đã thực hiện chuyển đổi từ Scalar sang TVF trong một số truy vấn khác và nó đã giải quyết vấn đề thực thi nối tiếp bắt buộc.

Đây là hàm vô hướng:

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

Đây là chức năng TVF được chuyển đổi.

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

Có điều gì sai với việc tôi thực hiện chức năng TVF đang ngăn truy vấn chạy ở chế độ song song.

Tôi sử dụng chức năng TVF trong truy vấn như dưới đây;

select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')

Truy vấn thực tế của tôi sử dụng chế độ xem khá phức tạp và nếu tôi nhận xét phần chức năng trong chế độ xem và thực thi, truy vấn sẽ chạy song song. Vì vậy, đây là chức năng buộc truy vấn chạy song song.

Truy vấn thực tế của tôi là ở định dạng dưới đây.

select 
dv.column1,
dv.column2,
---------
---------
--------
(select ReviewDueDate from dbo.FunctionResultTableVairable('a','b','c')) AS 'Columnx'
from
DemoView dv
Where 
condition1
conditon 2

Bất kỳ trợ giúp được đánh giá cao.


3
Kế hoạch truy vấn nói gì?
David Browne - Microsoft

2
Ngoài ra, có một sự khác biệt lớn giữa TVF nội tuyến và TVF đa câu lệnh, nếu TVF của bạn trả về cùng một hàng cho mỗi hàng trong truy vấn bên ngoài (vì nó chỉ lấy các hằng số) và bạn chỉ quan tâm đến một cột đầu ra , tại sao bạn lại đặt nó trong một truy vấn con trong danh sách chọn? Điều này chỉ làm cho nó có thể thực hiện nhiều lần mà không có lý do. Chỉ định đầu ra cho một biến và sau đó sử dụng biến trong truy vấn của bạn.
Aaron Bertrand

Câu trả lời:


5

có thể chuyển đổi chức năng vô hướng của tôi sang Inline TVF không?

Đúng. Một cái gì đó như dưới đây sẽ làm điều đó.

Nó vẫn còn khá nặng và nếu chạy tương quan có thể sẽ không hiệu quả. Như Aaron chỉ ra trong các ý kiến ​​bạn đang gọi điều này với các giá trị không đổi mặc dù vậy, hy vọng kế hoạch truy vấn phản ánh điều này và chỉ chạy nó một lần.

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); 

11

Forrest hầu hết là đúng, nhưng các chi tiết tốt hơn là:

Máy chủ SQL không thể song song sửa đổi các biến của bảng mà hàm của bạn sử dụng.

Trước khi thực thi xen kẽ của SQL Server 2017 , các ước tính hàng từ các hàm có giá trị của bảng nhiều câu lệnh rất thấp.

Một tác dụng phụ của việc này là các kế hoạch được chi phí rất thấp ở cấp thấp và thường sẽ không phá vỡ ngưỡng chi phí cho song song.


1
Được rồi, bạn có thể tìm kiếm bất kỳ giải pháp thay thế nào để truy vấn chính của tôi có thể chạy ở chế độ song song. Nhìn vào hàm vô hướng của tôi, có thể chuyển đổi hàm vô hướng của tôi sang TVF nội tuyến không?
user9516827

1
@ user9516827 bạn có thể có thể xâu chuỗi một số CTE lại với nhau để làm điều gì đó tương tự, nhưng tôi không biết liệu nó có đi song song, hoạt động tốt hơn không, v.v. Việc kiểm tra nó là tùy thuộc vào bạn.
Erik Darling

@MartinSmith: Truy vấn thực tế của tôi là một truy vấn rất phức tạp với rất nhiều tham gia và tham gia vào các khung nhìn, v.v. Hàm này được sử dụng cho một cột được chọn trong truy vấn chính và đó là lý do tại sao tôi đã cố gắng sửa nó. Ngoài ra, đây là LINQ -Có thể truy vấn được tạo ra (MySQL sp_executesql) và tôi có giới hạn là không hack mã .net. Cảm ơn
user9516827

10

SQL Server không thể song song hóa các TVF đa câu lệnh, đó là những gì là của bạn. Chỉ TVF nội tuyến có thể được song song.


1
Vì tôi có các biến trong đó nên tôi không thể chuyển đổi hàm vô hướng thành Inline TVF?
user9516827
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.