Chính xác thì No No Tham gia dự đoán có nghĩa là gì trong SQL Server?


23

MSDN " Thiếu tham gia lớp sự kiện dự đoán " nói rằng " chỉ ra rằng một truy vấn đang được thực thi không có biến vị ngữ tham gia ".

Nhưng thật không may, nó dường như không dễ dàng như vậy.

Ví dụ, tình huống rất đơn giản:

create table #temp1(i int);
create table #temp2(i int);
Select * from #temp1, #temp2 option (recompile);

Không có dữ liệu trong các bảng, cũng không có cảnh báo, mặc dù rõ ràng nó không có biến vị ngữ tham gia.

Nếu tôi xem tài liệu về SQL Server 2005 (cùng một liên kết, chỉ là phiên bản máy chủ khác), có thêm một câu: " Sự kiện này chỉ được tạo ra nếu cả hai bên tham gia trả lại nhiều hơn một hàng. " Điều này sẽ tạo ra cảm giác hoàn hảo trong tình huống trước. Không có dữ liệu, vì vậy cả hai bên trả về 0 hàng và không có cảnh báo. Chèn hàng, nhận cảnh báo. Ok, tuyệt

Nhưng đối với tình huống khó hiểu tiếp theo, tôi chèn cùng một giá trị vào cả hai bảng:

Insert into #temp1 (i) values (1)
Insert into #temp1 (i) values (1)
Insert into #temp2 (i) values (1)
Insert into #temp2 (i) values (1)

Va tôi lây:

-- no warning:
Select * from #temp1 t1 
    inner join #temp2 t2 on t1.i = t2.i 
option (recompile)
-- has warning:
Select * from #temp1 t1 
    inner join (select 1 i union all select 1) t2 on t1.i = t2.i 
option (recompile)

Tại sao cái này rất?

Lưu ý : một số tập lệnh tôi đã sử dụng để phát hiện các truy vấn xấu này trên máy chủ của mình.

  1. Tất nhiên, kế hoạch thực hiện các thủ tục
  2. sử dụng theo dõi máy chủ mặc định để tìm cảnh báo

    Declare @trace nvarchar(500);
    Select @trace = cast(value as nvarchar(500))
    From sys.fn_trace_getinfo(Null)
    Where traceid = 1 and property = 2;
    
    Select t.StartTime, te.name, *
    From sys.fn_trace_gettable(@trace, 1) t
        Inner join sys.trace_events te on t.EventClass = te.trace_event_id
        where EventClass = 80
    order by t.StartTime desc
  3. bộ đệm kế hoạch thực hiện, để tìm những kế hoạch có cảnh báo (như cái này)

    WITH XMLNAMESPACES (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
    SELECT
        Cast('<?SQL ' + st.text + ' ?>' as xml) sql_text,
        pl.query_plan,
        ps.execution_count,
        ps.last_execution_time,
        ps.last_elapsed_time,
        ps.last_logical_reads,
        ps.last_logical_writes
    FROM sys.dm_exec_query_stats ps with (NOLOCK)
        Cross Apply sys.dm_exec_sql_text(ps.sql_handle) st
        Cross Apply sys.dm_exec_query_plan(ps.plan_handle) pl
    WHERE pl.query_plan.value('(//Warnings/@NoJoinPredicate)[1]', 'bit') = 1
    Order By last_execution_time desc
    OPTION (RECOMPILE);

Câu trả lời:


17

Câu hỏi của bạn tương tự như câu hỏi này . Đôi khi SQL Server có thể xóa một vị từ tham gia khỏi truy vấn ban đầu.

Trong trường hợp bạn thấy cảnh báo vị ngữ tham gia, SQL Server phát hiện tại thời điểm biên dịch rằng bảng hằng số chỉ có một giá trị riêng biệt và giá trị 1đó được viết lại truy vấn như

SELECT *
FROM   (SELECT *
        FROM   #temp1 t1
        WHERE  t1.i = 1) t1
       CROSS JOIN (SELECT 1 i
                   UNION ALL
                   SELECT 1) t2 

Có một vị ngữ trên bảng quét #tempnhư sau[tempdb].[dbo].[#temp1].[i] =(1)

Vị từ nối on t1.i = t2.ikhông thể được loại bỏ theo cách này tại thời gian biên dịch khi sử dụng hai bảng hoặc nếu bảng hằng số chứa nhiều hơn một giá trị riêng biệt.


Thông tin thêm về điều này có thể được tìm thấy trong loạt Deep Deep Deep Tối ưu hóa truy vấn của Paul White .

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.