SQL Serverで「No Join Predicate」とはどういう意味ですか?


23

MSDN「Missing Join Predicate Event Class」は、「結合述語のないクエリが実行されていることを示しています」と述べています

しかし、残念ながら、それほど簡単ではないようです。

たとえば、非常に単純な状況:

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

テーブルにはデータがなく、警告もありませんが、明らかに結合述語はありません。

私はSQL Server 2005の(同じリンク、ちょうど他のサーバーバージョン)のドキュメントを見てみる場合は、余分な文章があります:「このイベントはの両側が1行以上のリターンに参加した場合にのみ生成されます。」これはなるだろう前の状況での完全な意味。データがないため、両側は0行を返し、警告を返しません。行を挿入すると、警告が表示されます。うんいいね。

しかし、次の混乱する状況のために、両方のテーブルに同じ値を挿入します。

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

そして私は得る:

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

これはなぜですか?

:サーバーでこれらの不適切なクエリを検出するために使用したスクリプト。

  1. もちろん、手続きの実行計画
  2. デフォルトのサーバートレースを使用して警告を見つけた

    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. 実行計画キャッシュ、警告のある計画を見つけるため(このような)

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

回答:


17

あなたの質問はに似て、この1。SQL Serverは、元のクエリから結合述語を削除できる場合があります。

結合述語の警告が表示される場合、SQL Serverはコンパイル時に定数のテーブルに1つの異なる値しかないことを検出し、その値は1クエリを次のように書き換えます。

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

#temp次のようなテーブルスキャンに関する述語があります[tempdb].[dbo].[#temp1].[i] =(1)

の結合述部は、on t1.i = t2.i2つのテーブルを使用する場合、または定数のテーブルに複数の異なる値が含まれる場合、コンパイル時にこの方法で削除できません。


これに関する詳細情報は、Paul WhiteQuery Optimizer Deep Diveシリーズにあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.