쿼리를 계속 실행하면서 SQL Server가 일부 행을 반환하는 이유는 무엇입니까?


33

"execute"를 쳤을 때 몇 개의 행을 보여주고 계속 커지는 쿼리가 있지만 쿼리는 아직 끝나지 않았습니다. 그러나 때로는 쿼리가 끝날 때까지 기다립니다.

왜 이런 일이 발생합니까? 이것을 제어하는 ​​방법이 있습니까?

답변:


43

평소와 마찬가지로 (대부분의 경우) 대답은 실행 계획에 있습니다.

행을 처리하고 다운 스트림으로 전달하기 전에 모든 행이 도착해야하는 특정 연산자가 있습니다. 예를 들면 다음과 같습니다.

  • 해시 조인 (해시 테이블 작성시)
  • 해시 매치
  • 정렬 (해시 흐름 구별 제외)

이러한 이유로 인해 차단 또는 정지 및 이동 연산자라고하며, 옵티마이 저가 데이터를 찾기 위해 많은 양의 데이터를 처리해야한다고 생각할 때 종종 선택됩니다.

스트리밍을 시작하거나 발견 된 행을 즉시 전달할 수있는 다른 연산자가 있습니다.

  • 중첩 루프
  • 인덱스 지원 병합 조인
  • 스트림 집계

쿼리가 데이터를 즉시 반환하기 시작하지만 즉시 완료되지 않는 경우 일반적으로 최적화 프로그램이 시작 비용이 낮은 연산자를 사용하여 일부 행을 빠르게 찾아 반환 할 계획을 선택했음을 나타냅니다.

이것은 사용자 또는 옵티마이 저가 도입 한 행 목표로 인해 발생할 수 있습니다.

SARGability 부족, 매개 변수 스니핑, 불충분 한 통계 등으로 인해 잘못된 계획을 선택한 경우에도 발생할 수 있지만 파악하는 데 더 많은 파기가 필요합니다.

자세한 내용은 Rob Farley의 블로그를 참조하십시오.

그리고 행 목표에 폴 화이트의 시리즈 여기 , 여기 , 여기 , 그리고 여기 .

SSMS에 대해 이야기하는 경우 행 버퍼가 채워지면 윌리 니 일뿐 만 아니라 행만 나타납니다.


14

관찰하고있는 내용을 이해하면 Management Studio에서 행을 렌더링 하는 방식 이며 SQL Server 행을 반환 하는 방식과는 거의 관련이 없습니다 . 실제로 큰 결과를 SSMS에 반환하고 그리드로 렌더링하려고하면 SSMS를 유지할 수없고 SQL Server가 앱에서 더 많은 행을 처리 할 때까지 기다리게됩니다. 이 경우 SQL Server 누적 ASYNC_NETWORK_IO대기가 표시됩니다.

SSMS가 그리드를 그릴 때보 다 텍스트를 더 빨리 그릴 수 있기 때문에 Results to Grid 대신 Results to Text를 사용하여 다소 제어 할 수 있지만 열 수 및 관련 데이터 유형에 따라 가독성에 영향을 줄 수 있습니다. SSMS가 실제로 해당 창에 결과를 쓰려고 결정하면 출력 버퍼가 얼마나 꽉 찼는 지에 따라 영향을받습니다.

당신이있을 때 여러 개의 문을, 당신은 메시지 창에 출력 결과를 렌더링하는 버퍼를 강제하려면, 당신은 문 사이에 트릭을 인쇄 조금 사용할 수 있습니다 :

RAISERROR('', 0, 1) WITH NOWAIT;

그러나 이것은 모든 출력이 단일 명령문에서 오는 경우 SSMS가 행을 더 빨리 렌더링하도록 할 때 도움이되지 않습니다.

보다 직접적으로 SSMS에서 렌더링하는 결과 수를 제한하여 제어 할 수 있습니다. 나는 사람들이 그리드에 백만 개의 행을 반환하는 데 걸리는 시간에 대해 불평하는 경우가 종종 있습니다. SSMS 그리드에서 백만 개의 행으로 지구상의 모든 사람들이 할 일이 무엇인지 모르겠습니다.

와 같은 일부 해킹이 있습니다. OPTION (FAST 100)첫 번째 100 행 (또는 외부가없는 경우 100 행)을 검색하는 데 최적화 ORDER BY되지만 나머지 행에 대한 검색 속도가 훨씬 느려질 수 있습니다. 전체적으로 비효율적이므로 실제로는 IMHO 옵션이 아닙니다.


1

귀하의 질문은 SQLServer 자체에 관한 것이 아니라 다음과 같습니다.

  • SQLServer
  • 회로망
  • 클라이언트 응용 프로그램으로서의 SSMS

이것을 제어하는 ​​방법이 있습니까?

짧은 답변 :

  1. 시도 sqlcmd대신에 ssms또는 sqlcmd의 -modessms
  2. 연결 및 세션 설정 확인

긴 대답 :

당연하지! 하지만 - PROB

  1. ssms에서 sqlcmd또는 sqlcmd-mode로 쿼리를 실행하십시오 .
  2. 네트워크 역할을 제외하려면 공유 메모리 연결로 서버에서 쿼리를 실행하십시오.
  3. 공유 메모리 연결을 사용해도 쿼리 성능이 만족스럽지 않으면 실행 계획을 분석하십시오. 네트워크를 통해 쿼리가 제대로 수행되지 않으면 네트워크 네트워크 관리자에게 도움을 요청하십시오. SSMS에서만 쿼리가 제대로 수행되지 않으면 추가로 읽으십시오.
  4. 이제 우리는 클라이언트 쪽 (이 경우에는 SMS)에 문제가 있음을 확신합니다. SSMS에서 연결 및 세션 설정을 확인하십시오. ssms 인터페이스를 믿지 말고 SQL 프로파일 러로 확인하십시오. 연결을 찾고 spid세션 설정의 전체 목록을 얻습니다. sqlcmd세션 설정과 비교하십시오 . 아무 것도 클릭하지 않으면 프로파일 러의 모든 세션 설정을 쿼리 스크립트로 복사하고 sqlcmd-mode 에서 실행 하고 점차적으로 설정을 변경하면 범인을 찾을 수 있습니다.

행운을 빕니다!


-2

sp_BlitzErik의 답변에 추가하려면 NOT IN ()하위 선택과 함께 a 를 사용하여 예를 들어보십시오 . 항목이 중첩 쿼리의 결과인지 여부를 확인하려면 (일반적으로) 전체 결과를 검색해야합니다.

따라서 이러한 쿼리의 성능을 향상시키는 쉬운 방법 중 하나는 side LEFT OUTER JOIN조건 RIGHT이 null 인 곳 으로 다시 작성하는 것 입니다 (물론 뒤집을 수는 있지만 누가 RIGHT OUTER JOINS? 를 사용 합니까). 이를 통해 결과가 즉시 반환됩니다.


나는 그렇게 생각하지 않습니다. 비교 된 열이 널 입력 가능하지 않은 경우, 3 가지 버전의 안티 조인 (NOT IN, NOT EXISTS, LEFT JOIN / IS NULL)에 대한 결과는 동일하고 계획은 일반적으로 동일해야합니다. 전체 결과를 검색 할 필요는 없습니다.
ypercubeᵀᴹ

부속 선택이 NOT IN 조건, WHERE t.x IN (<complex SELECT subquery>)동등한 LEFT JOIN을 확인하기 전에 전체 부속 선택을 평가해야하는 실제 복잡한 선택 인 경우 부속 조회도 평가해야합니다 ( LEFT JOIN (<complex SELECT subquery>) AS r ON r.x = t.x .... WHERE r.x IS NULLNO와 동일한 복잡한 계획 IN 버전).
ypercubeᵀᴹ

@ ypercubeᵀᴹ 그것은 과거에 나를 위해 일했다. 쿼리가 몇 분이 걸리고 초 단위로 돌아 오는 것을 보았습니다.
JimmyJames

@ ypercubeᵀᴹ Oracle에서 간단한 예를 작성했습니다 (죄송합니다. 현재 SQLServer에 액세스 할 수 없습니다). 그리고 그들은 분명히 다른 설명 계획을 가지고있었습니다. 아마도 그들은 의미있는 차이가 아니었지만 꽤 다르게 보입니다.
JimmyJames

@JimmyJames : 안정적인 성능을 원한다면 이러한 간단한 방법이 아니며 이러한 "최적화"는 SQLServer 버전에 매우 민감합니다. 그리고 오라클에 호소력을 가지지 마십시오 (어떤 버전?). 과거에는 SQLServer가 선호 NOT EXISTS되었지만 NOT IN쿼리 에서는 Oracle 이 선호 되었습니다. 그러나 오늘날 계획 생성기에서 오류로 간주되어야합니다.
Alex Yu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.