SQL Server에서“No Join Predicate”는 정확히 무엇을 의미합니까?


23

MSDN " Join Join Predicate 이벤트 클래스가 누락되었습니다 "는 " Join 술어 가없는 쿼리가 실행되고 있음을 나타냅니다 ."

그러나 불행히도 그렇게 쉬운 것처럼 보이지는 않습니다.

예를 들어 매우 간단한 상황은 다음과 같습니다.

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

테이블에는 데이터가 없으며 조인 술어도 없지만 경고는 없습니다.

SQL Server 2005 (동일한 링크, 다른 서버 버전)에 대한 설명서를 살펴보면 다음과 같은 추가 문장이 있습니다. " 이 이벤트는 조인의 양쪽이 둘 이상의 행을 반환하는 경우에만 생성됩니다. " 이전 상황에서의 완벽한 의미. 데이터가 없으므로 양쪽에서 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

귀하의 질문은 다음과 유사합니다 이것 . 때로는 SQL Server가 원래 쿼리에서 조인 조건자를 제거 할 수 있습니다.

조인 조건 자 경고가 표시되는 경우 SQL Server는 컴파일 할 때 상수 테이블에 하나의 고유 한 값만 있고 해당 값은 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.i두 테이블을 사용할 때 또는 상수 테이블에 둘 이상의 고유 값이 포함 된 경우 컴파일 시간에 이러한 방식으로 결합 술어를 제거 할 수 없습니다.


이에 대한 자세한 정보는 Paul WhiteQuery Optimizer Deep Dive 시리즈 에서 찾을 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.