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


338

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


2
SQL Server Management Studio에서 실행 계획 탭을 어떻게 닫습니까?
Paul McCarthy

2
@Paul 당신은 그것을 위해 Ctrl + R을 누를 수 있습니다. 메시지 및 실행 계획을 포함하여 전체 결과 섹션을 닫습니다.
Nisarg

답변:


501

실행 계획을 얻는 방법에는 여러 가지가 있으며, 사용 계획은 상황에 따라 다릅니다. 일반적으로 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 예상치가 꺼져있는 문제를 진단 할 때 필수적입니다.

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

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

또한보십시오:


8
미래 독자를위한 참고 사항 : SET STATISTICS XML ON쿼리 시작과 개미를 계획 출력에 표시 하지 않으려 SET STATISTICS XML OFF|ON 주변 영역을 넣으십시오 : 쿼리에 원하지 않는 반복 (WHILE)이 포함되어있을 때 유용합니다. 실행 계획에서 볼 수 있습니다 (그렇지 않으면 SQL SERVER가 표시하기에는 너무 무겁고 길 것입니다).
Roimer

2
@MonsterMMORPG 방법 4를 사용한 다음 선택할 수 있습니다. 예를 들어 <a href=" github.com/StackExchange/dapper-dot-net"> Dapper.net </… > connection.Query <string> ( "SELECT 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) 텍스트가 N '% 인 경우 원본 쿼리가 여기에옵니다 (%' "); %는 쿼리의 하위 집합 만 사용하는 경우입니다.
bmarks

2
@ 조회 실행 계획을 해석하기 위해 귀하가 링크 한 책의 2 판은 2009 년부터 작성되었습니다. 2016 년에도 그 목적을 위해 정말 좋은 자료라고 말할 수 있습니까?
Abdul

3
@Abdul 동일한 작성자 인 Grant Fritchey는 최신 버전의 SQL Server를 다루는 SQL Server Query Performance Tuning이라는 최신 책을 보유하고 있습니다.
thelem

42

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

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

18

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

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

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

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

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

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

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


15

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

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

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

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

SSMS의 새 쿼리 버튼

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

실행 계획

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

예상 실행 계획

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

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

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

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

실제 실행 계획

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


14

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

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

SQL Sentry Plan Explorer 창 스크린 샷

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

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

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


1
타사 도구에 대해 누가 이야기 했습니까?
basher

12
@basher : OP는 MS 도구 또는 다른 방법으로 수단을 제한하지 않았습니다. 그렇다면 타사 도구와 관련된 답변이 부적절한 도구라고 생각하는 것은 무엇입니까?
Alexander Abakumov

3
Speaking of third-party tools아무도 타사 도구를 언급하지 않았을 때 대답의 시작을 어떻게 표현했는지 농담 이었습니다.
basher

4
@basher : 오, 잘 잡아! 감사합니다! 나는 대답을 다시 썼다. 의견이 있으시면 언제든지 의견을 보내주십시오.
Alexander Abakumov


7

이벤트를 통해 확장 이벤트 세션에서 쿼리 계획을 얻을 수 있습니다 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 이상을 사용하지 않는 경우 여기에 게시 된 다른 답변 중 하나를 강력히 제안합니다.


5

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 이상에서만 사용할 수 있습니다


4

SQL Server Management Studio (이미 설명)와 마찬가지로 여기에 설명 된대로 Datagrip을 사용할 수도 있습니다 .

  1. SQL 문을 마우스 오른쪽 단추로 클릭하고 Explain plan을 선택하십시오.
  2. 출력 분할 창에서 계획을 클릭하십시오.
  3. 기본적으로 쿼리의 트리 표현이 나타납니다. 쿼리 계획을 보려면 시각화 표시 아이콘을 클릭하거나 Ctrl + Shift + Alt + U를 누르십시오.

3

이전에 말한 모든 것 외에 알아야 할 중요한 사항이 있습니다.

쿼리 계획은 종종 너무 복잡하여 내장 된 XML 열 유형으로 표현할 수 없으며 127 수준 의 중첩 요소 로 제한 됩니다. sys.dm_exec_query_planNULL이전 MS SQL 버전에서 오류를 반환 하거나 오류를 발생 시키는 이유 중 하나 이므로 일반적으로 sys.dm_exec_text_query_plan 을 사용하는 것이 더 안전합니다 . 후자는 또한 전체 배치가 아닌 특정 명세서에 대한 계획을 선택하는 유용한 보너스 기능을 가지고 있습니다. 현재 실행중인 명령문에 대한 계획을 보는 데 사용하는 방법은 다음과 같습니다.

SELECT p.query_plan
FROM sys.dm_exec_requests AS r
OUTER APPLY sys.dm_exec_text_query_plan(
                r.plan_handle,
                r.statement_start_offset,
                r.statement_end_offset) AS p

그러나 결과 테이블의 텍스트 열은 XML 열에 비해 그리 편리하지 않습니다. 내용을 파일에 저장하지 않고 별도의 탭에서 다이어그램으로 열려면 결과를 클릭 할 수 있도록 약간의 트릭을 사용할 수 있습니다 (단지 사용할 수는 없음 CAST(... AS XML)). 단일 행 :

SELECT Tag = 1, Parent = NULL, [ShowPlanXML!1!!XMLTEXT] = query_plan
FROM sys.dm_exec_text_query_plan(
                -- set these variables or copy values
                -- from the results of the above query
                @plan_handle,
                @statement_start_offset,
                @statement_end_offset)
FOR XML EXPLICIT

3

SET STATISTICS XML ON을 사용하여 powershell을 통해 실제 계획을 얻을 수도 있습니다. 나는 다중 문 계획을 하나의 계획으로 병합하기 위해 작성했습니다.

    ########## BEGIN : SCRIPT VARIABLES #####################
    [string]$server = '.\MySQLServer'
    [string]$database = 'MyDatabase'
    [string]$sqlCommand = 'EXEC sp_ExampleSproc'
    [string]$XMLOutputFileName = 'sp_ExampleSproc'
    [string]$XMLOutputPath = 'C:\SQLDumps\ActualPlans\'
    ########## END   : SCRIPT VARIABLES #####################

    #Set up connection
    $connectionString = "Persist Security Info=False;Integrated Security=true;Connection Timeout=0;Initial Catalog=$database;Server=$server"
    $connection = new-object system.data.SqlClient.SQLConnection($connectionString)

    #Set up commands
    $command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)
    $command.CommandTimeout = 0
    $commandXMLActPlanOn = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML ON",$connection)
    $commandXMLActPlanOff = new-object system.data.sqlclient.sqlcommand("SET STATISTICS XML OFF",$connection)

    $connection.Open()

    #Enable session XML plan
    $result = $commandXMLActPlanOn.ExecuteNonQuery()

    #Execute SP and return resultsets into a dataset
    $adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command
    $dataset = New-Object System.Data.DataSet
    $adapter.Fill($dataSet) | Out-Null

    #Set up output file name and path
    [string]$fileNameDateStamp = get-date -f yyyyMMdd_HHmmss
    [string]$XMLOutputFilePath = "$XMLOutputPath$XMLOutputFileName`_$fileNameDateStamp.sqlplan"

    #Pull XML plans out of dataset and merge into one multi-statement plan
    [int]$cntr = 1
    ForEach($table in $dataset.Tables)
    {
            if($table.Columns[0].ColumnName -eq "Microsoft SQL Server 2005 XML Showplan")
            {

                [string]$fullXMLPlan = $Table.rows[0]."Microsoft SQL Server 2005 XML Showplan"

                if($cntr -eq 1)
                    {

                    [regex]$rx = "\<ShowPlanXML xmlns\=.{1,}\<Statements\>"
                    [string]$startXMLPlan = $rx.Match($fullXMLPlan).Value
                    [regex]$rx = "\<\/Statements\>.{1,}\<\/ShowPlanXML\>"
                    [string]$endXMLPlan = $rx.Match($fullXMLPlan).Value

                    $startXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                    }

                [regex]$rx = "\<StmtSimple.{1,}\<\/StmtSimple\>"
                [string]$bodyXMLPlan = $rx.Match($fullXMLPlan).Value

                $bodyXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

                $cntr += 1
            } 
    }

    $endXMLPlan | out-file -Append -FilePath $XMLOutputFilePath

    #Disable session XML plan
    $result = $commandXMLActPlanOff.ExecuteNonQuery()

    $connection.Close()

2

이 기사 에서 설명했듯이 SQL Server를 사용할 때 얻을 수있는 두 가지 실행 계획 유형이 있습니다.

예상 실행 계획

예상 실행 계획은 SQL 쿼리를 실행하지 않고 Optimizer에 의해 생성됩니다.

예상 실행 계획을 얻으려면 SHOWPLAN_ALL쿼리를 실행하기 전에 설정 을 활성화해야 합니다.

SHOWPLAN_ALL ON 설정

이제 다음 SQL 쿼리를 실행할 때

SELECT p.id
FROM post p
WHERE EXISTS (
  SELECT 1
  FROM post_comment pc
  WHERE
    pc.post_id = p.id AND
    pc.review = 'Bingo'
)
ORDER BY p.title
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY

SQL Server는 다음과 같은 예상 실행 계획을 생성합니다.

| NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost | EstimateExecutions |
|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|--------------------|
| 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03374284       | NULL               |
| 2      | 1      | Top                  | 10           | 0           | 3.00E-06    | 15         | 0.03374284       | 1                  |
| 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000504114 | 146        | 0.03373984       | 1                  |
| 5      | 4      | Inner Join           | 46.698       | 0           | 0.00017974  | 146        | 0.02197446       | 1                  |
| 6      | 5      | Clustered Index Scan | 43           | 0.004606482 | 0.0007543   | 31         | 0.005360782      | 1                  |
| 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0161733        | 43                 |

쿼리를 실행 한 후 예상 실행 계획을 가져 오려면 SHOWPLAN_ALLas 를 비활성화해야합니다 . 그렇지 않으면 현재 데이터베이스 세션이 제공된 SQL 쿼리를 실행하는 대신 예상 실행 계획 만 생성합니다.

SET SHOWPLAN_ALL OFF

SQL Server Management Studio 예상 계획

SQL Server Management Studio 응용 프로그램에서는 CTRL+L키 바로 가기를 눌러 모든 SQL 쿼리에 대한 예상 실행 계획을 쉽게 얻을 수 있습니다 .

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

실제 실행 계획

실제 SQL 실행 계획은 SQL 쿼리를 실행할 때 Optimizer에 의해 생성됩니다. 데이터베이스 테이블 통계가 정확하면 실제 계획은 예상과 크게 다르지 않아야합니다.

SQL Server에서 실제 실행 계획을 얻으려면 STATISTICS IO, TIME, PROFILE다음 SQL 명령으로 설명 된대로 설정 을 활성화해야합니다 .

SET STATISTICS IO, TIME, PROFILE ON

이제 이전 쿼리를 실행할 때 SQL Server는 다음 실행 계획을 생성합니다.

| Rows | Executes | NodeId | Parent | LogicalOp            | EstimateRows | EstimateIO  | EstimateCPU | AvgRowSize | TotalSubtreeCost |
|------|----------|--------|--------|----------------------|--------------|-------------|-------------|------------|------------------|
| 10   | 1        | 1      | 0      | NULL                 | 10           | NULL        | NULL        | NULL       | 0.03338978       |
| 10   | 1        | 2      | 1      | Top                  | 1.00E+01     | 0           | 3.00E-06    | 15         | 0.03338978       |
| 30   | 1        | 4      | 2      | Distinct Sort        | 30           | 0.01126126  | 0.000478783 | 146        | 0.03338679       |
| 41   | 1        | 5      | 4      | Inner Join           | 44.362       | 0           | 0.00017138  | 146        | 0.02164674       |
| 41   | 1        | 6      | 5      | Clustered Index Scan | 41           | 0.004606482 | 0.0007521   | 31         | 0.005358581      |
| 41   | 41       | 7      | 5      | Clustered Index Seek | 1            | 0.003125    | 0.0001581   | 146        | 0.0158571        |

SQL Server parse and compile time:
   CPU time = 8 ms, elapsed time = 8 ms.

(10 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post'. Scan count 0, logical reads 116, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'post_comment'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(6 row(s) affected)

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 1 ms.

쿼리를 실행 한 후 실제 실행 계획을 세우려면 다음 STATISTICS IO, TIME, PROFILE ON과 같이 설정 을 비활성화해야합니다 .

SET STATISTICS IO, TIME, PROFILE OFF

SQL Server Management Studio 실제 계획

SQL Server Management Studio 응용 프로그램에서는 CTRL+M키 바로 가기를 눌러 모든 SQL 쿼리에 대한 예상 실행 계획을 쉽게 얻을 수 있습니다 .

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

SQL Server 사용시 실행 계획을 얻는 방법에 대한 자세한 내용은 이 문서를 참조하십시오 .


0

실행 계획을 설명하는 것은 매우 상세하고 읽기 시간이 많이 걸리지 만 요약하면 쿼리 전에 'explain'을 사용하면 처음 실행 된 부분을 포함하여 많은 정보를 제공해야합니다. 이것에 대해 좀 더 자세히 읽고 싶다면 이것에 관한 작은 블로그를 작성하여 올바른 심판을 지시하십시오. https://medium.com/swlh/jetbrains-datagrip-explain-plan-ac406772c470

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