<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
	<id>https://dbstudy.co.kr/w/index.php?action=history&amp;feed=atom&amp;title=%EC%8B%A4%ED%96%89_%EA%B3%84%ED%9A%8D</id>
	<title>실행 계획 - 편집 역사</title>
	<link rel="self" type="application/atom+xml" href="https://dbstudy.co.kr/w/index.php?action=history&amp;feed=atom&amp;title=%EC%8B%A4%ED%96%89_%EA%B3%84%ED%9A%8D"/>
	<link rel="alternate" type="text/html" href="https://dbstudy.co.kr/w/index.php?title=%EC%8B%A4%ED%96%89_%EA%B3%84%ED%9A%8D&amp;action=history"/>
	<updated>2026-09-10T11:54:52Z</updated>
	<subtitle>이 문서의 편집 역사</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>https://dbstudy.co.kr/w/index.php?title=%EC%8B%A4%ED%96%89_%EA%B3%84%ED%9A%8D&amp;diff=1804&amp;oldid=prev</id>
		<title>Dbstudy: 새 문서: == 실행 계획 == * SSMS에서 쿼리 → 실제 실행 계획 포함 켜기. (Ctrl + M) &lt;source lang=sql&gt; SET STATISTICS IO ON; SET STATISTICS TIME ON;  SELECT * FROM dbo.EMP WHERE EMPNO = 1000;  &lt;/source&gt; - 실행하면 결과 창 외에 실행 계획(Execution Plan) 탭이 나타납니다.  &lt;source lang=sql&gt; SELECT  └─ Hash Match      ├─ Index Scan      └─ Index Scan &lt;/source&gt; * Index Seek =&gt; oracle의 index range/unique scan  * Actual Plan 에서 실제 row 확...</title>
		<link rel="alternate" type="text/html" href="https://dbstudy.co.kr/w/index.php?title=%EC%8B%A4%ED%96%89_%EA%B3%84%ED%9A%8D&amp;diff=1804&amp;oldid=prev"/>
		<updated>2026-09-09T13:42:56Z</updated>

		<summary type="html">&lt;p&gt;새 문서: == 실행 계획 == * SSMS에서 쿼리 → 실제 실행 계획 포함 켜기. (Ctrl + M) &amp;lt;source lang=sql&amp;gt; SET STATISTICS IO ON; SET STATISTICS TIME ON;  SELECT * FROM dbo.EMP WHERE EMPNO = 1000;  &amp;lt;/source&amp;gt; - 실행하면 결과 창 외에 실행 계획(Execution Plan) 탭이 나타납니다.  &amp;lt;source lang=sql&amp;gt; SELECT  └─ Hash Match      ├─ Index Scan      └─ Index Scan &amp;lt;/source&amp;gt; * Index Seek =&amp;gt; oracle의 index range/unique scan  * Actual Plan 에서 실제 row 확...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 실행 계획 ==&lt;br /&gt;
* SSMS에서 쿼리 → 실제 실행 계획 포함 켜기. (Ctrl + M)&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
SET STATISTICS IO ON;&lt;br /&gt;
SET STATISTICS TIME ON;&lt;br /&gt;
&lt;br /&gt;
SELECT *&lt;br /&gt;
FROM dbo.EMP&lt;br /&gt;
WHERE EMPNO = 1000;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
- 실행하면 결과 창 외에 실행 계획(Execution Plan) 탭이 나타납니다.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
SELECT&lt;br /&gt;
 └─ Hash Match&lt;br /&gt;
     ├─ Index Scan&lt;br /&gt;
     └─ Index Scan&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Index Seek =&amp;gt; oracle의 index range/unique scan&lt;br /&gt;
&lt;br /&gt;
* Actual Plan 에서 실제 row 확인하기 &lt;br /&gt;
** SQL Server에서도 Cardinality Estimation 문제가 있는지 보는 것이 중요. &lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
Estimated Number of Rows = 10&lt;br /&gt;
Actual Number of Rows    = 1,500,000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* SSMS 실행계획에서 우클릭하여: Save Execution Plan As...  &amp;gt; .sqlplan파일로 저장&lt;br /&gt;
* oracle DBMS_XPLAN 과 비슷 &lt;br /&gt;
&amp;lt;source lang=xml&amp;gt;&lt;br /&gt;
&amp;lt;ShowPlanXML ...&amp;gt;&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/ShowPlanXML&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== I/O를 더 자세하게 확인 ===&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
SET NOCOUNT ON;&lt;br /&gt;
&lt;br /&gt;
SET STATISTICS IO ON;&lt;br /&gt;
SET STATISTICS TIME ON;&lt;br /&gt;
&lt;br /&gt;
SELECT O.ORDER_ID,&lt;br /&gt;
       O.CUSTOMER_ID,&lt;br /&gt;
       O.ORDER_DATE,&lt;br /&gt;
       O.AMOUNT&lt;br /&gt;
FROM dbo.ORDERS O&lt;br /&gt;
WHERE O.CUSTOMER_ID = 100&lt;br /&gt;
  AND O.ORDER_DATE &amp;gt;= &amp;#039;2026-01-01&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
SET STATISTICS IO OFF;&lt;br /&gt;
SET STATISTICS TIME OFF;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
Table &amp;#039;ORDERS&amp;#039;.&lt;br /&gt;
Scan count 1,&lt;br /&gt;
logical reads 23500,&lt;br /&gt;
physical reads 0,&lt;br /&gt;
read-ahead reads 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
SQL Server Execution Times:&lt;br /&gt;
   CPU time = 850 ms,&lt;br /&gt;
   elapsed time = 920 ms.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SET STATISTICS IO에서 특히 중요한 항목 ====&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Table &amp;#039;ORDERS&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
Scan count 1,&lt;br /&gt;
logical reads 125000,&lt;br /&gt;
physical reads 0,&lt;br /&gt;
read-ahead reads 120000,&lt;br /&gt;
lob logical reads 0,&lt;br /&gt;
lob physical reads 0,&lt;br /&gt;
lob read-ahead reads 0.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Scan count&lt;br /&gt;
*: 테이블/인덱스에 대한 Scan 횟수입니다.&lt;br /&gt;
*Nested Loop와 같이 반복 접근이 발생하면 눈여겨봐야 합니다.&lt;br /&gt;
* logical reads&lt;br /&gt;
*:-메모리에 있는 데이터 페이지를 읽은 횟수입니다.&lt;br /&gt;
* physical reads&lt;br /&gt;
*: 디스크에서 실제 페이지를 읽은 횟수입니다.&lt;br /&gt;
* SQL Server는 데이터가 버퍼 캐시에 올라가 있을 경우:&lt;br /&gt;
*: physical reads = 0 이어도 logical reads = 1000000 일 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
=== 실제 튜닝 템플릿 ===&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
SET NOCOUNT ON;&lt;br /&gt;
&lt;br /&gt;
SET STATISTICS IO ON;&lt;br /&gt;
SET STATISTICS TIME ON;&lt;br /&gt;
&lt;br /&gt;
-- 대상 SQL&lt;br /&gt;
SELECT&lt;br /&gt;
    O.ORDER_ID,&lt;br /&gt;
    O.CUSTOMER_ID,&lt;br /&gt;
    O.ORDER_DATE,&lt;br /&gt;
    O.AMOUNT&lt;br /&gt;
FROM dbo.ORDERS O&lt;br /&gt;
WHERE O.CUSTOMER_ID = 100&lt;br /&gt;
  AND O.ORDER_DATE &amp;gt;= &amp;#039;2026-01-01&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
SET STATISTICS IO OFF;&lt;br /&gt;
SET STATISTICS TIME OFF;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Oracle 과 비교표 ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Oracle 과 비교표&lt;br /&gt;
|-&lt;br /&gt;
! Oracle !! SQL Server&lt;br /&gt;
|-&lt;br /&gt;
|A-Rows                         || Actual Rows&lt;br /&gt;
|-&lt;br /&gt;
|E-Rows                         ||  Estimated Rows&lt;br /&gt;
|-&lt;br /&gt;
|Buffers                       ||   logical reads&lt;br /&gt;
|-&lt;br /&gt;
|Physical Reads                 ||  physical reads&lt;br /&gt;
|-&lt;br /&gt;
|Execution Time                ||  CPU / elapsed&lt;br /&gt;
|-&lt;br /&gt;
|TABLE ACCESS FULL             ||   Table Scan&lt;br /&gt;
|-&lt;br /&gt;
|INDEX RANGE SCAN             ||    Index Seek&lt;br /&gt;
|-&lt;br /&gt;
|INDEX FULL SCAN              ||    Index Scan&lt;br /&gt;
|-&lt;br /&gt;
|HASH JOIN                    ||    Hash Match&lt;br /&gt;
|-&lt;br /&gt;
|NESTED LOOPS                 ||    Nested Loops&lt;br /&gt;
|-&lt;br /&gt;
|SORT                         ||    Sort&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Query Store ===&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
실행 횟수&lt;br /&gt;
CPU Time&lt;br /&gt;
Duration&lt;br /&gt;
Logical Reads&lt;br /&gt;
Physical Reads&lt;br /&gt;
Memory&lt;br /&gt;
Plan 변경&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=sql&amp;gt;&lt;br /&gt;
SELECT TOP 20&lt;br /&gt;
       qt.query_sql_text,&lt;br /&gt;
       rs.execution_count,&lt;br /&gt;
       rs.avg_duration,&lt;br /&gt;
       rs.avg_cpu_time,&lt;br /&gt;
       rs.avg_logical_io_reads&lt;br /&gt;
FROM sys.query_store_query_text qt&lt;br /&gt;
JOIN sys.query_store_query q&lt;br /&gt;
  ON qt.query_text_id = q.query_text_id&lt;br /&gt;
JOIN sys.query_store_plan p&lt;br /&gt;
  ON q.query_id = p.query_id&lt;br /&gt;
JOIN sys.query_store_runtime_stats rs&lt;br /&gt;
  ON p.plan_id = rs.plan_id&lt;br /&gt;
ORDER BY rs.avg_logical_io_reads DESC;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dbstudy</name></author>
	</entry>
</feed>