[sql] SQL Server에서 쿼리 실행 계획을 어떻게 얻습니까?

Microsoft SQL Server에서 쿼리 / 저장 프로 시저에 대한 쿼리 실행 계획을 어떻게 얻을 수 있습니까?



답변

실행 계획을 얻는 방법에는 여러 가지가 있으며, 사용 계획은 상황에 따라 다릅니다. 일반적으로 SQL Server Management Studio를 사용하여 계획을 얻을 수 있지만 어떤 이유로 SQL Server Management Studio에서 쿼리를 실행할 수없는 경우 SQL Server 프로파일 러 또는 검사를 통해 계획을 얻는 것이 도움이 될 수 있습니다. 계획 캐시.

방법 1-SQL Server Management Studio 사용

SQL Server에는 실행 계획을 매우 쉽게 캡처 할 수있는 몇 가지 깔끔한 기능이 포함되어 있습니다. “실제 실행 계획 포함”메뉴 항목 ( “쿼리”메뉴 아래에 있음)을 선택하고 쿼리를 정상적으로 실행하십시오. .

Action Execution Plan 메뉴 항목 포함

스토어드 프로 시저에서 명령문에 대한 실행 계획을 얻으려는 경우 스토어드 프로 시저를 다음과 같이 실행해야합니다.

exec p_Example 42

쿼리가 완료되면 결과 창에 “실행 계획”이라는 추가 탭이 나타납니다. 많은 명세서를 실행 한 경우이 탭에 많은 계획이 표시 될 수 있습니다.

실행 계획의 스크린 샷

여기에서 SQL Server Management Studio의 실행 계획을 검사하거나 계획을 마우스 오른쪽 단추로 클릭하고 “실행 계획을 다른 이름으로 저장 …”을 선택하여 계획을 XML 형식으로 파일에 저장할 수 있습니다.

방법 2-SHOWPLAN 옵션 사용

이 방법은 방법 1과 매우 유사하지만 (실제로 SQL Server Management Studio가 내부적으로 수행하는 작업 임) 완전성을 위해 또는 SQL Server Management Studio를 사용할 수없는 경우 포함 시켰습니다.

조회를 실행하기 전에 다음 명령문 중 하나 를 실행하십시오 . 명령문은 배치에서 유일한 명령문이어야합니다. 즉, 다른 명령문을 동시에 실행할 수 없습니다.

SET SHOWPLAN_TEXT ON
SET SHOWPLAN_ALL ON
SET SHOWPLAN_XML ON
SET STATISTICS PROFILE ON
SET STATISTICS XML ON -- The is the recommended option to use

이는 연결 옵션이므로 연결 당 한 번만 실행하면됩니다. 이 시점부터 실행 계획에는 원하는 형식으로 실행 계획이 포함 된 추가 결과 집합 이 동반됩니다. 일반적으로 계획을 보는 것처럼 쿼리를 실행하면됩니다.

완료되면 다음 명령문으로이 옵션을 해제 할 수 있습니다.

SET <<option>> OFF

실행 계획 형식 비교

선호도가 높지 않으면 STATISTICS XML옵션 을 사용하는 것이 좋습니다 . 이 옵션은 SQL Server Management Studio의 “실제 실행 계획 포함”옵션과 동일하며 가장 편리한 형식으로 대부분의 정보를 제공합니다.

  • SHOWPLAN_TEXT -쿼리를 실행하지 않고 기본 텍스트 기반 예상 실행 계획을 표시합니다.
  • SHOWPLAN_ALL -쿼리를 실행하지 않고 비용 추정과 함께 텍스트 기반 예상 실행 계획을 표시합니다.
  • SHOWPLAN_XML-쿼리를 실행하지 않고 비용을 예측하여 XML 기반 예상 실행 계획을 표시합니다. 이는 SQL Server Management Studio의 “예상 실행 계획 표시 …”옵션과 같습니다.
  • STATISTICS PROFILE -쿼리를 실행하고 텍스트 기반 실제 실행 계획을 표시합니다.
  • STATISTICS XML-쿼리를 실행하고 XML 기반 실제 실행 계획을 표시합니다. 이는 SQL Server Management Studio의 “실제 실행 계획 포함”옵션과 동일합니다.

방법 3-SQL Server 프로파일 러 사용

쿼리를 직접 실행할 수 없거나 쿼리를 직접 실행할 때 쿼리가 느리게 실행되지 않으면 쿼리 계획이 제대로 수행되지 않는다는 것을 기억하면 SQL Server 프로파일 러 추적을 사용하여 계획을 캡처 할 수 있습니다. 아이디어는 “Showplan”이벤트 중 하나를 캡처하는 추적이 실행되는 동안 쿼리를 실행하는 것입니다.

로드에 따라 프로덕션 환경에서이 방법을 사용할 있지만주의해야합니다. 은 SQL Server 프로파일 메커니즘은 데이터베이스에 미치는 영향을 최소화하도록 설계되어 있지만이 없을 것이라는 점을 의미하지 않는다 어떤 성능에 미치는 영향. 데이터베이스 사용량이 많은 경우 추적에서 올바른 계획을 필터링하고 식별하는 데 문제가있을 수도 있습니다. 귀중한 데이터베이스에서이 작업을 수행하는 데 만족하는지 DBA에 분명히 확인해야합니다!

  1. SQL Server 프로파일 러를 열고 추적을 기록하려는 원하는 데이터베이스에 연결하는 새 추적을 작성하십시오.
  2. “이벤트 선택”탭에서 “모든 이벤트 표시”를 확인하고 “성능”-> “Showplan XML”행을 확인하고 추적을 실행하십시오.
  3. 추적이 실행되는 동안 느리게 실행되는 쿼리를 실행하려면 필요한 작업을 수행하십시오.
  4. 조회가 완료 될 때까지 기다린 후 추적을 중지하십시오.
  5. 추적을 저장하려면 SQL Server 프로파일 러에서 계획 xml을 마우스 오른쪽 단추로 클릭하고 “이벤트 데이터 추출 …”을 선택하여 계획을 파일로 XML 형식으로 저장하십시오.

얻는 계획은 SQL Server Management Studio의 “실제 실행 계획 포함”옵션과 같습니다.

방법 4-쿼리 캐시 검사

쿼리를 직접 실행할 수없고 프로파일 러 추적을 캡처 할 수없는 경우에도 SQL 쿼리 계획 캐시를 검사하여 예상 계획을 얻을 수 있습니다.

SQL Server DMV 를 쿼리하여 계획 캐시를 검사합니다 . 다음은 모든 캐시 된 쿼리 계획 (xml)을 SQL 텍스트와 함께 나열하는 기본 쿼리입니다. 대부분의 데이터베이스에서는 결과를 관심있는 계획으로 만 필터링하기 위해 추가 필터링 절을 추가해야합니다.

SELECT UseCounts, Cacheobjtype, Objtype, TEXT, query_plan
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)

이 쿼리를 실행하고 계획 XML을 클릭하여 계획을 새 창에서 엽니 다. 마우스 오른쪽 단추를 클릭하고 “다른 이름으로 실행 계획 저장 …”을 선택하여 계획을 파일로 XML 형식으로 저장하십시오.

노트:

테이블 및 인덱스 스키마에서 저장된 데이터 및 테이블 통계에 이르기까지 많은 요소가 관련되어 있기 때문에 항상 관심있는 데이터베이스 (일반적으로 성능이 발생하는 데이터베이스)에서 실행 계획을 얻으려고 노력해야합니다. 문제).

암호화 된 저장 프로 시저에 대한 실행 계획을 캡처 할 수 없습니다.

“실제”vs “예상 된”실행 계획

실제 실행 계획은 반면, SQL 서버가 실제로 쿼리를 실행 하나입니다 추정 실행 계획 SQL 서버는 그것이 무엇을 작동 쿼리를 실행하지 않고 않습니다. 논리적으로 동일하지만 실제 실행 계획은 쿼리를 실행할 때 실제로 일어난 일에 대한 추가 세부 정보 및 통계를 포함하므로 훨씬 유용합니다. 이는 통계가 최신이 아닌 경우와 같이 SQL Server 예상치가 꺼져있는 문제를 진단 할 때 필수적입니다.

쿼리 실행 계획을 어떻게 해석합니까?

은 (무료) 책에 충분한 주제 입니다 은 그 자체 에 입니다.

또한보십시오:


답변

이미 게시 된 포괄적 인 답변 외에도 정보를 추출하기 위해 프로그래밍 방식으로 실행 계획에 액세스하는 것이 유용합니다. 이에 대한 예제 코드는 다음과 같습니다.

DECLARE @TraceID INT
EXEC StartCapture @@SPID, @TraceID OUTPUT
EXEC sp_help 'sys.objects' /*<-- Call your stored proc of interest here.*/
EXEC StopCapture @TraceID

StartCapture정의 예

CREATE PROCEDURE StartCapture
@Spid INT,
@TraceID INT OUTPUT
AS
DECLARE @maxfilesize BIGINT = 5
DECLARE @filepath NVARCHAR(200) = N'C:\trace_' + LEFT(NEWID(),36)

EXEC sp_trace_create @TraceID OUTPUT, 0, @filepath, @maxfilesize, NULL

exec sp_trace_setevent @TraceID, 122, 1, 1
exec sp_trace_setevent @TraceID, 122, 22, 1
exec sp_trace_setevent @TraceID, 122, 34, 1
exec sp_trace_setevent @TraceID, 122, 51, 1
exec sp_trace_setevent @TraceID, 122, 12, 1
-- filter for spid
EXEC sp_trace_setfilter @TraceID, 12, 0, 0, @Spid
-- start the trace
EXEC sp_trace_setstatus @TraceID, 1

StopCapture정의 예

CREATE  PROCEDURE StopCapture
@TraceID INT
AS
WITH  XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/showplan' as sql),
      CTE
     as (SELECT CAST(TextData AS VARCHAR(MAX)) AS TextData,
                ObjectID,
                ObjectName,
                EventSequence,
                /*costs accumulate up the tree so the MAX should be the root*/
                MAX(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
         FROM   fn_trace_getinfo(@TraceID) fn
                CROSS APPLY fn_trace_gettable(CAST(value AS NVARCHAR(200)), 1)
                CROSS APPLY (SELECT CAST(TextData AS XML) AS xPlan) x
                CROSS APPLY (SELECT T.relop.value('@EstimatedTotalSubtreeCost',
                                            'float') AS EstimatedTotalSubtreeCost
                             FROM   xPlan.nodes('//sql:RelOp') T(relop)) ca
         WHERE  property = 2
                AND TextData IS NOT NULL
                AND ObjectName not in ( 'StopCapture', 'fn_trace_getinfo' )
         GROUP  BY CAST(TextData AS VARCHAR(MAX)),
                   ObjectID,
                   ObjectName,
                   EventSequence)
SELECT ObjectName,
       SUM(EstimatedTotalSubtreeCost) AS EstimatedTotalSubtreeCost
FROM   CTE
GROUP  BY ObjectID,
          ObjectName

-- Stop the trace
EXEC sp_trace_setstatus @TraceID, 0
-- Close and delete the trace
EXEC sp_trace_setstatus @TraceID, 2
GO


답변

Microsoft SQL Server Management Studio를 사용한다고 가정

  • 들어 예상 쿼리 계획 당신은 눌러 Ctrl 키 + L 또는 다음 버튼을 누릅니다.

여기에 이미지 설명을 입력하십시오

  • 들어 실제 쿼리 계획 , 당신은 눌러 Ctrl 키 + M 또는 쿼리를 실행하기 전에 다음 버튼을 누릅니다.

여기에 이미지 설명을 입력하십시오

  • 들어 라이브 쿼리 계획 (만 2016 SSMS에서), 쿼리를 실행하기 전에 다음과 같은 버튼을 사용합니다.

여기에 이미지 설명을 입력하십시오


답변

이전 답변에서 설명한 방법 외에도 무료 실행 계획 뷰어 및 쿼리 최적화 도구 ApexSQL Plan 을 사용할 수도 있습니다. (최근에 부딪친)을 사용할 수도 있습니다.

ApexSQL Plan을 SQL Server Management Studio에 설치 및 통합 할 수 있으므로 SSMS에서 직접 실행 계획을 볼 수 있습니다.

ApexSQL Plan에서 예상 실행 계획보기

  1. SSMS에서 새 쿼리 버튼을 클릭하고 쿼리 텍스트 창에 쿼리 텍스트를 붙여 넣습니다. 마우스 오른쪽 버튼을 클릭하고 상황에 맞는 메뉴에서 “추정 실행 계획 표시”옵션을 선택하십시오.

SSMS의 새 쿼리 버튼

  1. 실행 계획 다이어그램이 결과 섹션의 실행 계획 탭에 표시됩니다. 다음으로 실행 계획을 마우스 오른쪽 버튼으로 클릭하고 상황에 맞는 메뉴에서 “ApexSQL 계획에서 열기”옵션을 선택하십시오.

실행 계획

  1. 예상 실행 계획은 ApexSQL 계획에서 열리 며 쿼리 최적화를 위해 분석 될 수 있습니다.

예상 실행 계획

ApexSQL Plan에서 실제 실행 계획보기

쿼리의 실제 실행 계획을 보려면 앞에서 언급 한 2 단계부터 계속하십시오. 그러나 이제 예상 계획이 표시되면 ApexSQL 계획의 기본 리본 막대에서 “실제”버튼을 클릭하십시오.

메인 리본 바에서“실제”버튼을 클릭하십시오

“실제”버튼을 클릭하면 실제 실행 계획이 다른 실행 계획 데이터와 함께 비용 매개 변수의 세부 미리보기와 함께 표시됩니다.

실제 실행 계획

실행 계획을 보는 방법에 대한 자세한 내용은 이 링크를 참조하십시오 .


답변

쿼리 실행 계획을 얻고 심층 분석하는 데 가장 좋아하는 도구는 SQL Sentry Plan Explorer입니다. 입니다. SSMS보다 실행 계획의 세부 분석 및 시각화에 훨씬 사용하기 쉽고 편리하며 포괄적입니다.

다음은 도구에서 제공하는 기능에 대한 아이디어를 제공하는 샘플 스크린 샷입니다.

SQL Sentry Plan Explorer 창 스크린 샷

도구에서 사용할 수있는보기 중 하나 일뿐입니다. 앱 창의 맨 아래에있는 일련의 탭을 통해 다양한 유형의 실행 계획 표현과 유용한 추가 정보를 얻을 수 있습니다.

또한 매일 무료 버전을 사용하지 못하게하거나 결국 Pro 버전을 구매하도록 강요하는 무료 버전의 제한 사항을 발견하지 못했습니다. 따라서 무료 버전을 고수하려는 경우 금지 사항이 없습니다.

업데이트 : ( 마틴 스미스 덕분에 ) 계획 탐색기는 무료입니다! 자세한 내용은 http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view 를 참조하십시오.


답변

이벤트를 통해 확장 이벤트 세션에서 쿼리 계획을 얻을 수 있습니다 query_post_execution_showplan. 다음은 샘플 XEvent 세션입니다.

/*
    Generated via "Query Detail Tracking" template.
*/
CREATE EVENT SESSION [GetExecutionPlan] ON SERVER
ADD EVENT sqlserver.query_post_execution_showplan(
    ACTION(package0.event_sequence,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)),

/* Remove any of the following events (or include additional events) as desired. */
ADD EVENT sqlserver.error_reported(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.module_end(SET collect_statement=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.rpc_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sp_statement_completed(SET collect_object_name=(1)
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_batch_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0)))),
ADD EVENT sqlserver.sql_statement_completed(
    ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.database_id,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.query_plan_hash,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_frame,sqlserver.tsql_stack)
    WHERE ([package0].[greater_than_uint64]([sqlserver].[database_id],(4)) AND [package0].[equal_boolean]([sqlserver].[is_system],(0))))
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

세션을 생성 한 후 (SSMS에서) 개체 탐색기로 이동하여 관리 | 확장 이벤트 | 세션. “GetExecutionPlan”세션을 마우스 오른쪽 단추로 클릭하고 시작하십시오. 다시 마우스 오른쪽 버튼을 클릭하고 “실시간 데이터보기”를 선택하십시오.

그런 다음 새 쿼리 창을 열고 하나 이상의 쿼리를 실행하십시오. AdventureWorks를위한 하나는 다음과 같습니다.

USE AdventureWorks;
GO

SELECT p.Name AS ProductName,
    NonDiscountSales = (OrderQty * UnitPrice),
    Discounts = ((OrderQty * UnitPrice) * UnitPriceDiscount)
FROM Production.Product AS p
INNER JOIN Sales.SalesOrderDetail AS sod
    ON p.ProductID = sod.ProductID
ORDER BY ProductName DESC;
GO

잠시 후 “GetExecutionPlan : Live Data”탭에 일부 결과가 표시됩니다. 그리드에서 query_post_execution_showplan 이벤트 중 하나를 클릭 한 다음 그리드 아래의 “쿼리 계획”탭을 클릭하십시오. 다음과 비슷해야합니다.

여기에 이미지 설명을 입력하십시오

편집 : XEvent 코드 및 스크린 샷은 SQL / SSMS 2012 w / SP2에서 생성되었습니다. 당신은 SQL 2008 / R2를 사용하는 경우, 당신은 할 수 그것을 실행하기 위해 스크립트를 조정할 수 있습니다. 그러나 해당 버전에는 GUI가 없으므로 실행 계획 XML을 추출하여 * .sqlplan 파일로 저장 한 후 SSMS에서 열어야합니다. 번거 롭습니다. XEvents는 SQL 2005 이전 버전에는 존재하지 않았습니다. 따라서 SQL 2012 이상을 사용하지 않는 경우 여기에 게시 된 다른 답변 중 하나를 강력히 제안합니다.


답변

SQL Server 2016+부터는 성능을 모니터링하기 위해 Query Store 기능이 도입되었습니다. 쿼리 계획 선택 및 성능에 대한 통찰력을 제공합니다. 추적 또는 확장 이벤트를 완전히 대체하지는 않지만 버전에서 버전으로 발전함에 따라 SQL Server의 향후 릴리스에서 완전한 기능을 갖춘 쿼리 저장소를 얻을 수 있습니다. 쿼리 저장소의 기본 흐름

  1. SQL Server 기존 구성 요소는 Query Store Manager를 사용하여 쿼리 저장소와 상호 작용합니다.
  2. Query Store Manager는 사용할 상점을 결정한 후 실행을 해당 상점 (계획 또는 런타임 통계 또는 조회 대기 통계)으로 전달합니다.
    • 계획 저장소-실행 계획 정보 유지
    • 런타임 통계 저장소-실행 통계 정보 지속
    • 쿼리 대기 통계 저장소-지속 대기 통계 정보.
  3. 계획, 런타임 통계 및 대기 저장소는 쿼리 저장소를 SQL Server의 확장으로 사용합니다.

여기에 이미지 설명을 입력하십시오

  1. 쿼리 저장소 활성화 : 쿼리 저장소는 서버의 데이터베이스 수준에서 작동합니다.

    • 쿼리 저장소는 기본적으로 새 데이터베이스에 대해 활성화되어 있지 않습니다.
    • 마스터 또는 tempdb데이터베이스에 대한 쿼리 저장소를 활성화 할 수 없습니다 .
    • 사용 가능한 DMV

      sys.database_query_store_options (Transact-SQL)

  2. 쿼리 저장소에서 정보 수집 : 쿼리 저장소 DMV (데이터 관리 뷰)를 사용하여 세 개의 저장소에서 사용 가능한 모든 정보를 수집합니다.

참고 : 쿼리 대기 통계 저장소는 SQL Server 2017 이상에서만 사용할 수 있습니다