SQL Server'da “Katılma Öngörü Yok” tam olarak ne anlama geliyor?


23

MSDN " Etkinlik Sınıfını Kaybetme Eksikliği Sınıfı ", " birleştirme yüklemesi olmayan bir sorgunun yürütülmekte olduğunu belirtir " diyor .

Ancak ne yazık ki bu kadar kolay görünmüyor.

Örneğin, çok basit bir durum:

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

Tablolarda veri yok, hiçbir uyarı yok, açık bir şekilde birleştirme yordamı yok.

SQL Server 2005'in belgelerine bakarsam (aynı bağlantı, yalnızca diğer sunucu sürümü), ek bir cümle var: " Bu olay yalnızca birleşmenin her iki tarafı birden fazla satır döndürdüğünde üretilir. " önceki durumda mükemmel anlamda. Veri yok, bu yüzden her iki taraf da 0 satır döndürüyor ve uyarı vermiyor. Satır ekle, uyarı al. Tamam iyi.

Fakat bir sonraki kafa karıştırıcı durum için, her iki tabloya da aynı değerleri giriyorum:

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

Ve anladım:

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

Bu neden böyle?

Not : Sunucumdaki bu kötü sorguları tespit etmek için kullandığım bazı komut dosyaları.

  1. Tabii ki, işlemlerin yürütme planı
  2. uyarıları bulmak için varsayılan sunucu izlemesi kullanılır

    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. İcra planı önbelleği, uyarıları olan planları bulmak için (bunun gibi)

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

Yanıtlar:


17

Sorunuz benzer bu bir . Bazen SQL Server, bir birleşim yüklemini orijinal sorgudan kaldırabilir.

Bir birleşim yüklemi uyarısı gördüğünüzde, SQL Server derleme zamanında sabitlerin tablosunun yalnızca bir değere sahip olduğunu tespit eder ve bu değer 1sorguyu yeniden yazar.

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

Tablo taramasında bir yüklem vardır #tempaşağıdaki gibi[tempdb].[dbo].[#temp1].[i] =(1)

on t1.i = t2.iİki tablo kullanılırken veya sabitler tablosu birden fazla farklı değer içeriyorsa, derleme zamanında bu şekilde birleştirme yordamı kaldırılamaz.


Bu konuda diğer bilgiler bulunabilir Paul Beyaz 'ın Sorgu Doktoru Derine İnme serisi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.