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)
これはなぜですか?
注:サーバーでこれらの不適切なクエリを検出するために使用したスクリプト。
- もちろん、手続きの実行計画
デフォルトのサーバートレースを使用して警告を見つけた
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
実行計画キャッシュ、警告のある計画を見つけるため(このような)
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);