Làm thế nào đến một biến bảng đang cải thiện hiệu năng của một truy vấn trong tình huống này?


8

đối với trường hợp cụ thể này, tôi sẽ cố gắng giải thích bên dưới, sử dụng biến bảng đang hoạt động tốt hơn so với không sử dụng biến bảng.

Tôi muốn biết tại sao, và nếu có thể, hãy loại bỏ biến bảng.

đây là truy vấn sử dụng biến bảng:

USE [BISource_UAT]
GO

set statistics io on
SET STATISTICS TIME ON

    SET NOCOUNT ON;

    DECLARE @OrderStartDate DATETIME = '15-feb-2015'
    DECLARE @OrderEndDate DATETIME = '28-feb-2016'
    DECLARE @tmp TABLE
    (
    strBxOrderNo VARCHAR(20)
    ,sintReturnId INT
    )  

    INSERT INTO @tmp
    SELECT  strBxOrderNo
            ,sintReturnId
    FROM    TABLEBACKUPS.dbo.tblBReturnHistory rh
    WHERE   rh.sintReturnStatusId in ( 3 )
    AND     rh.dtmAdded >= @OrderStartDate
    AND     rh.dtmAdded < @OrderEndDate

    SELECT 
             op.lngPaymentID
            ,op.strBxOrderNo
            ,op.sintPaymentTypeID
            ,op.strCurrencyCode
            ,op.strBCCurrencyCode
            ,op.decPaymentAmount
            ,op.decBCPaymentAmount
            ,ap.strAccountCode
            ,o.sintMarketID
            ,o.sintOrderChannelID
            ,o.sintOrderTypeID
            ,CASE   WHEN opgv.lngpaymentID IS NULL THEN NULL
                     -- Not a Voucher = Null
                WHEN gvp.strIssuedBxOrderNo IS NULL THEN 0 ELSE 1 
              END AS [IsPromoVoucher] -- Is a Voucher - check type
            ,o.sdtmOrdCreated

    FROM    @tmp rh

            INNER JOIN TABLEBACKUPS.dbo.tblBReturn r 
                    ON r.sintReturnId = rh.sintReturnId 
                   AND r.strBxOrderNo = rh.strBxOrderNo

            INNER JOIN bocss2.dbo.tblBOrder o 
                    ON o.strBxOrderNo = r.strBxOrderNo

            INNER JOIN Bocss2.dbo.tblBOrderPayment op 
                    ON op.strBxOrderNo = o.strBxOrderNo

            INNER JOIN TABLEBACKUPS.dbo.tblBOrderItemReturn AS oir 
                    ON r.sintReturnId = oir.sintReturnID 
                   AND r.strBxOrderNo = oir.strBxOrderNo

            INNER JOIN Bocss2.dbo.tblBOrderItem AS i 
                    ON i.strBxOrderNo = oir.strBxOrderNo 
                   AND i.sintOrderSeqNo = oir.sintOrderSeqNo

            INNER JOIN TABLEBACKUPS.dbo.tblBAccountParticipant ap 
                   ON o.lngAccountParticipantID = ap.lngParticipantID

            LEFT OUTER JOIN TABLEBACKUPS.dbo.tblBOrderPaymentGiftVoucher opgv 
                         ON op.lngPaymentID = opgv.lngPaymentID

            LEFT OUTER JOIN TABLEBACKUPS.dbo.tblBGiftVoucher gv 
                         ON opgv.strVoucherNumber = gv.strVoucherNumber

            LEFT OUTER JOIN TABLEBACKUPS.dbo.tblBGiftVoucherPromotion gvp 
                         ON gvp.strIssuedBxOrderNo = gv.strIssuedBxOrderNo

    WHERE   oir.decReturnFinalAmount > 0
    AND     o.sdtmOrdCreated >= @OrderStartDate

điều này tạo ra các số liệu thống kê sau:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 78 ms, elapsed time = 86 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
Table '#BF0B2154'. Scan count 0, logical reads 1957, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBReturnHistory'. Scan count 1, logical reads 13, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 16 ms,  elapsed time = 9 ms.
Table 'tblBGiftVoucherPromotion'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBGiftVoucher'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderPaymentGiftVoucher'. Scan count 0, logical reads 452, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderItem'. Scan count 0, logical reads 904, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderPayment'. Scan count 186, logical reads 1649, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBAccountParticipant'. Scan count 0, logical reads 7112, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrder'. Scan count 3557, logical reads 14267, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderItemReturn'. Scan count 1951, logical reads 5865, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBReturn'. Scan count 0, logical reads 3902, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#BF0B2154'. Scan count 1, logical reads 7, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 125 ms,  elapsed time = 138 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

sử dụng showplan lòng trên tôi muốn hiển thị kế hoạch truy vấn:

phần đầu tiên của truy vấn - điền vào biến bảng nhập mô tả hình ảnh ở đây

phần thứ hai của truy vấn: sử dụng biến bảng và nối các bảng khác: nhập mô tả hình ảnh ở đây

Đây là kế hoạch XML của truy vấn bằng cách sử dụng biến bảng.

bây giờ đây là cùng một truy vấn KHÔNG sử dụng biến bảng:

USE [BISource_UAT]
GO

set statistics io on
SET STATISTICS TIME ON

    SET NOCOUNT ON;

    DECLARE @OrderStartDate DATETIME = '15-feb-2015'
    DECLARE @OrderEndDate DATETIME = '28-feb-2016'

    SELECT 
             op.lngPaymentID
            ,op.strBxOrderNo
            ,op.sintPaymentTypeID
            ,op.strCurrencyCode
            ,op.strBCCurrencyCode
            ,op.decPaymentAmount
            ,op.decBCPaymentAmount
            ,ap.strAccountCode
            ,o.sintMarketID
            ,o.sintOrderChannelID
            ,o.sintOrderTypeID
            ,CASE   WHEN opgv.lngpaymentID IS NULL 
               THEN NULL -- Not a Voucher = Null
                WHEN gvp.strIssuedBxOrderNo IS NULL 
                THEN 0 ELSE 1 END AS [IsPromoVoucher] 
                -- Is a Voucher - check type
            ,o.sdtmOrdCreated

    FROM    TABLEBACKUPS.dbo.tblBReturnHistory rh

            INNER JOIN TABLEBACKUPS.dbo.tblBReturn r 
                    ON r.sintReturnId = rh.sintReturnId 
                   AND r.strBxOrderNo = rh.strBxOrderNo

            INNER JOIN bocss2.dbo.tblBOrder o 
                    ON o.strBxOrderNo = r.strBxOrderNo
                   AND o.sdtmOrdCreated >= @OrderStartDate

            INNER JOIN Bocss2.dbo.tblBOrderPayment op 
                    ON op.strBxOrderNo = o.strBxOrderNo

            INNER JOIN TABLEBACKUPS.dbo.tblBOrderItemReturn AS oir 
                    ON r.sintReturnId = oir.sintReturnID 
                   AND r.strBxOrderNo = oir.strBxOrderNo
                   AND oir.decReturnFinalAmount > 0

            INNER JOIN Bocss2.dbo.tblBOrderItem AS i 
                    ON i.strBxOrderNo = oir.strBxOrderNo 
                   AND i.sintOrderSeqNo = oir.sintOrderSeqNo

            INNER JOIN TABLEBACKUPS.dbo.tblBAccountParticipant ap 
                   ON o.lngAccountParticipantID = ap.lngParticipantID

            LEFT OUTER JOIN TABLEBACKUPS.dbo.tblBOrderPaymentGiftVoucher opgv 
                         ON op.lngPaymentID = opgv.lngPaymentID

            LEFT OUTER JOIN TABLEBACKUPS.dbo.tblBGiftVoucher gv 
                         ON opgv.strVoucherNumber = gv.strVoucherNumber

            LEFT OUTER JOIN TABLEBACKUPS.dbo.tblBGiftVoucherPromotion gvp 
                         ON gvp.strIssuedBxOrderNo = gv.strIssuedBxOrderNo

    WHERE   rh.sintReturnStatusId in ( 3 )
    AND     rh.dtmAdded >= @OrderStartDate
    AND     rh.dtmAdded < @OrderEndDate

khi nhìn vào số liệu thống kê, đây là những gì chúng ta có:

SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBGiftVoucher'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBAccountParticipant'. Scan count 1, logical reads 32, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBReturn'. Scan count 1, logical reads 170, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderItemReturn'. Scan count 0, logical reads 35849, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderPayment'. Scan count 9408, logical reads 87643, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderItem'. Scan count 1950, logical reads 8336, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrder'. Scan count 1951, logical reads 7835, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBReturnHistory'. Scan count 1, logical reads 13, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBOrderPaymentGiftVoucher'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'tblBGiftVoucherPromotion'. Scan count 1, logical reads 27, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 625 ms,  elapsed time = 612 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

Bây giờ, liên quan đến kế hoạch thực hiện ở định dạng văn bản:

thiết lập các tham số

nhập mô tả hình ảnh ở đây

Bây giờ là phần quan trọng, chạy chương trình: nhập mô tả hình ảnh ở đây

Đây là kế hoạch XML của truy vấn KHÔNG sử dụng biến bảng.

Nhưng làm thế nào mà sử dụng biến bảng tôi nhận được ít đọc hơn, ít I / O hơn và việc thực thi (không xóa bộ đệm) luôn nhanh hơn?

Tôi có thể cung cấp bất kỳ tập lệnh tạo bảng, hoặc bất cứ điều gì cần thiết để hiểu rõ hơn về tình huống này.

chỉ cần đăng bất kỳ bình luận ở đây và tôi sẽ trả lời.

đây là một câu hỏi tương tự:

Tại sao sử dụng biến bảng nhanh hơn hai lần so với bảng #temp trong trường hợp cụ thể này?

khi chạy các truy vấn sau CHECKPOINT ; DBCC DROPCLEANBUFFERS ; kết quả là:

truy vấn với biến bảng

truy vấn với biến bảng

truy vấn không có biến bảng

truy vấn không có biến bảng


Có sự khác biệt nào không nếu bạn giữ bộ lọc điều kiện where từ truy vấn đầu tiên trong điều kiện nơi của truy vấn thứ hai thay vì di chuyển chúng sang điều kiện nối bên trong? Điều này: WHERE oir.decReturnFinalAmount> 0 VÀ o.sdtmOrdCreated> = @OrderStartDate
BateTech

@BateTech khi tôi chuyển các điều kiện từ bên trong INNER THAM GIA sang mệnh đề WHERE, sau khi xóa bộ nhớ cache, thời gian CPU tăng từ 203 lên 281 và thời gian trôi qua tăng từ 865 lên 4029. Số lần đọc logic cho một số bảng cũng tăng lên .
Marcello Miorelli

Câu trả lời:


8

Các yếu tố chính trong trò chơi ở đây là:

  • Trình tối ưu hóa không cố gắng tìm kế hoạch tốt nhất; Mục tiêu của nó là tìm ra một kế hoạch hợp lý một cách nhanh chóng
  • Nó giả sử truy vấn sẽ được chạy với bộ đệm lạnh
  • Mô hình chi phí được sử dụng ủng hộ I / O tuần tự hơn I / O ngẫu nhiên
  • Tìm kiếm lặp đi lặp lại vào một chỉ mục được giả định là được phân phối ngẫu nhiên

Ước tính cardinality cho một biến bảng là 1 hàng (trừ khi xảy ra biên dịch lại mức câu lệnh hoặc cờ theo dõi 2453 đang hoạt động). Ước tính thấp này dẫn đến một kế hoạch chi phí rất thấp, có chiến lược điều hướng dựa trên các vòng lặp lồng nhau. Kế hoạch này có thể tiếp tục có hiệu lực đối với số lượng hàng tương đối thấp, đặc biệt nếu dữ liệu cần thiết không cần phải đọc từ bộ lưu trữ liên tục.

Với ước tính cardinality chính xác hơn, trình tối ưu hóa ủng hộ một kế hoạch sử dụng phép nối băm và một vài lần quét. Điều này dường như rẻ hơn so với một chiến lược điều hướng, với các giả định được liệt kê ở trên; đặc biệt liên quan đến bộ đệm lạnh và chi phí quét tuần tự tương đối thấp so với nhiều lần tìm kiếm (giả sử mẫu I / O phần lớn ngẫu nhiên).

Kế hoạch biến bảng có thể chậm hơn so với phương án thay thế nếu dữ liệu cần thiết không có trong bộ nhớ - hoặc có thể không . Mô hình chi phí chính xác là như vậy - một mô hình - các số chính xác được sử dụng có thể không đại diện cho phần cứng và cấu hình của bạn và các giả định được đưa ra có thể không hợp lệ trong các trường hợp cụ thể.

Tất cả những cảnh báo này được áp dụng đặc biệt cho các truy vấn chi phí thấp (cả hai đều như vậy) vì những thay đổi chi phí nhỏ có thể tạo ra các hình dạng kế hoạch rất khác nhau. Trên thực tế, cả hai kế hoạch đều thành công ở chỗ chúng tạo ra kết quả đủ nhanh và hiệu quả .

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.