1

다음과 같은 두 가지 쿼리가 있습니다. 원본은 첫 번째이고 두 번째는 약간의 "업그레이드"입니다. 처음에는 손가락을 완전히 새로 고침 버튼을 누르기 전에 거의 1 초가 걸리고 두 번째 키는 끝납니다.쿼리 대 쿼리 - 왜 다른 쿼리보다 더 빠른 이유는 무엇입니까?

내 질문 : 이유가 무엇입니까?

첫 번째와 두 번째 유일한 차이점은 coalesce를 사용하여 berp.ID_PART_SESSION과 (과) 비교할 값을 얻고 두 번째는 같은 선택을하기 위해 두 개의 SELECT 문을 함께 사용하는 것입니다.

여전히 동일한 결과를 얻으려면 작업량이 적어 져야하므로 첫 번째 작업이 더 빨라야한다고 생각합니다 (원래 병합을 사용한 이유). 내가 실행 계획을 해독하는 방법이 약하다는 것을 고려해 보면 누군가 두 번째 쿼리가 첫 번째 쿼리보다 훨씬 나은 이유를 설명해 줄 수 있습니까?

declare @animator varchar 
SELECT TOP 1 @animator = FULL_NAME 
FROM T_BERP berp 
INNER JOIN dbo.T_INTERV i ON i.ID_INTERV = berp.ID_INTERV 
WHERE berp.VERSION = 1 
    AND berp.PRINCIPAL = 1 
    AND berp.DELETED = 0 
    AND berp.CANCELLED = 0 
    AND berp.ID_PART_SESSION = (
     select coalesce(pss.ID_PART_SESSION, psst.ID_PART_SESSION) 
     from t_bersp b 
     LEFT JOIN T_PART_SESSION pss ON b.ID_PART_SESSION = pss.ID_PART_SESSION 
     LEFT JOIN T_PSS_TEMP psst ON b.ID_PSS_TEMP = psst.ID_PSS_TEMP 
     where ID_BERSP = 4040) 

declare @animator varchar 
SELECT TOP 1 @animator = FULL_NAME 
FROM dbo.T_BERP berp 
INNER JOIN dbo.T_INTERV i ON i.ID_INTERV = berp.ID_INTERV 
WHERE berp.VERSION = 1 
    AND berp.PRINCIPAL = 1 
    AND berp.DELETED = 0 
    AND berp.CANCELLED = 0 
    AND berp.ID_PART_SESSION IN (
     select pss.ID_PART_SESSION 
     from dbo.t_bersp b 
     LEFT JOIN dbo.T_PART_SESSION pss ON b.ID_PART_SESSION = pss.ID_PART_SESSION 
     where ID_BERSP = 4040 
     union 
     select psst.ID_PART_SESSION 
     from dbo.t_bersp b 
     LEFT JOIN dbo.T_PSS_TEMP psst ON b.ID_PSS_TEMP = psst.ID_PSS_TEMP 
     where ID_BERSP = 4040) 
+5

두 쿼리를 비교해야 할 때마다 일반적으로 [실행 계획이 어떻게 보이는지 확인하는] 쉬운 첫 단계입니다 (http://www.sql-server-performance.com/tips/query_execution_plan_analysis_p1.aspx). 일단 당신이 질문을하면 계획을 추가 할 것입니다. –

+0

초기 생각은 맨 위의'='와 하위 쿼리의 맨 아래에있는 'IN' 이었지만 상관 관계가 없으므로 문제가 될 것이라고 생각하지 않습니다 ... – JNK

+0

첫 번째 쿼리의 또 다른 차이점이 있습니다 '='를 사용하고 두 번째는 'IN'을 사용합니다. 또한 관련없는 경고로서, ORDER BY없이 TOP 1을 사용하면 버그를 추적하기가 매우 어려워 질 수 있습니다. 여러 레코드가 반환되는 순서는 주문하지 않은 경우 불확정합니다. 일반적으로 디스크의 인덱스 또는 물리적 순서의 정렬 순서와 일치하지만 보증은 없습니다. – Rozwel

답변

0

나는 그것이 합병 성명서 일 것입니다. 나는 합병이 where 절 앞에 적용되게 될 것이라고 믿습니다. 따라서 두 테이블의 각 조합을 실제로 처리하고 where 절과 일치하는 테이블을 필터링합니다.

+0

SQL Server가 처리 할 수있는 엄청나게 멍청한 방법 일 것입니다 ... 당신이 옳을 수도 있고 수수께끼를 설명 할 수도 있지만 그런 차선책이 끝내라. –

2

대 당신의 쿼리에서 여러 테이블의 상대적 크기와 인덱스를 이해하지 않고 확실한 대답을 제공하기 어려울 것이다. 한 가지 가능성 : t_part_session 및 t_pss_temp가 모두 큰 경우 쿼리 최적화 프로그램은 첫 번째 쿼리의 내부 SELECT에있는 두 개의 LEFT JOIN을 사용하여 비효율적 인 작업을 수행하고있을 수 있습니다.

EDIT : 두 쿼리에 LEFT JOIN이 있지만 두 가지를 함께 사용하면 쿼리 1이 성능과 UNION (쿼리 2)에 나쁜 영향을 미칠 수 있습니다. 미안 처음에 명확하지 않은 경우.

DECLARE @animator VARCHAR 

SELECT TOP 1 @animator = full_name 
FROM t_berp berp 
     INNER JOIN dbo.t_interv i 
     ON i.id_interv = berp.id_interv 
WHERE berp.version = 1 
     AND berp.principal = 1 
     AND berp.deleted = 0 
     AND berp.cancelled = 0 
     AND berp.id_part_session = (SELECT 
      Coalesce(pss.id_part_session, psst.id_part_session) 
            FROM t_bersp b 
              LEFT JOIN t_part_session pss 
              ON b.id_part_session = 
               pss.id_part_session 
              LEFT JOIN t_pss_temp psst 
              ON b.id_pss_temporaire = 
               psst.id_pss_temporaire 
            WHERE id_bersp = 4040) 

DECLARE @animator VARCHAR 

SELECT TOP 1 @animator = full_name 
FROM dbo.t_berp berp 
     INNER JOIN dbo.t_interv i 
     ON i.id_interv = berp.id_interv 
WHERE berp.version = 1 
     AND berp.principal = 1 
     AND berp.deleted = 0 
     AND berp.cancelled = 0 
     AND berp.id_part_session IN (SELECT pss.id_part_session 
            FROM dbo.t_bersp b 
              LEFT JOIN dbo.t_part_session pss 
              ON b.id_part_session = 
               pss.id_part_session 
            WHERE id_bersp = 4040 
            UNION 
            SELECT psst.id_part_session 
            FROM dbo.t_bersp b 
              LEFT JOIN dbo.t_pss_temp psst 
              ON b.id_pss_temporaire = 
               psst.id_pss_temporaire 
            WHERE id_bersp = 4040) 

대 : 쉽게 귀하의 질문에 (에 StackOverflow의 편집기에서 {} 아이콘과 결합)을 Instant SQL Formatter가 쿼리를 만들기 위해

또한, 나는 매우 읽을 같은 도구를 추천합니다

+0

-1 - LEFT JOIN은 두 번째 쿼리에도 모두 있으므로 "대답"은 기본적으로 "모르겠지만 코드를 더 잘 포맷하십시오"라고 표시됩니다. – JNK

+0

예 LEFT JOIN이 두 쿼리에 모두 있지만 내 추측은 함께 두 가지는 성능에 나쁜 영향을 미칠 수 있다는 것이 었습니다. 미안하지만 분명하지 않다. 가치가있는 것을 위해, 나는 실행 계획이 이것을 해결하기 위해 먼 길을 가겠다는 Chris의 의견에 동의한다. –

+0

죄송합니다. 코드를 형식화하려고 시도했는데 역 따옴표를 사용하여 코드를 작성하는 것을 보았습니다. 그래서 충분하다고 가정하고 역 인용 부호로 코드를 래핑했습니다. –

0

두 쿼리를 SSMS의 동일한 배치에 넣고 실행 계획을 표시 할 수 있습니다. 이렇게하면 나란히 볼 수있을뿐 아니라 상대 비용이 표시됩니다.

IN (UNION)은 두 번째를 쉽게 병렬 처리 할 수 ​​있다고 생각합니다.

+0

글쎄, 그게 훨씬 더 혼란스러워 - 첫 번째 (그리고 가장 느린) 쿼리는 27 %의 비용 (배치 대비)을 가지고 있고 두 번째 쿼리는 73 %라는 것을 말해 준다. –

+0

@Alex 파리에서 실제 또는 예상되는 것은? 두 번째는 병렬 처리를 사용합니까? 실제 통계는 읽기와 어떤 차이가 있습니까? –

+0

"실제 실행 계획 포함"이 선택되었습니다. 어디서나 병렬에 대한 언급이 없습니다. 첫 번째 쿼리에는 생각 화살표가 포함 된 항목이 하나 있습니다.이 쿼리는 쿼리 비용의 42 %를 차지하는 클러스터 된 인덱스 스캔입니다. 클러스터 된 인덱스 검색의 경우 35 % 두 번째 쿼리에는 하나의 큰 항목 비용이 있습니다. 키 조회의 경우 74 %입니다. 그 중 하나라도 도움이 될지 확실하지 않은 경우 ... –

관련 문제