PC · IT · DB/Oracle

[오라클] 오라클 실행 계획 Cost &CPU, 플랜 보는법 (Oracle Explain plan Cost & CPU)

뿌레도 2023. 8. 24. 21:46
728x90

[오라클] 오라클 실행 계획 Cost &CPU, 플랜 보는법 (Oracle Explain plan Cost & CPU)

 오라클 플랜에서 나오는 COST는 쿼리 실행에 소요되는 예상 비용을 나타냅니다. 이 비용은 쿼리 실행에 필요한 리소스 사용량과 관련이 있으며, 쿼리 실행 속도에 영향을 미칩니다.

 COST는 일반적으로 CPU, 메모리, 디스크 I/O 등의 리소스 사용량을 고려하여 계산됩니다. 쿼리 실행 계획에서 각 단계의 비용이 계산되고, 이 비용은 쿼리 실행 계획의 최적화에 사용됩니다. 최적화 관점에서는 비용이 낮을수록 쿼리 실행 속도가 빨라지며, 따라서 더 효율적인 실행 계획을 선택할 수 있습니다.

 COST는 다양한 요소에 의해 결정됩니다. 예를 들어, 테이블의 크기, 인덱스의 유무, 조인 조건, 필터링 조건 등이 비용에 영향을 줄 수 있습니다. 이러한 요소들은 쿼리 실행 계획의 선택과정에서 고려되며, 최적의 실행 계획을 선택하기 위해 비용을 최소화하는 방향으로 최적화가 수행됩니다.

 실제로 COST는 쿼리 실행 속도에 직접적인 영향을 미칩니다. 일반적으로 비용이 낮을수록 쿼리 실행 속도가 빨라지며, 따라서 더 효율적인 쿼리 실행이 가능해집니다. 하지만 COST는 예상 비용이므로, 실제 실행 시에는 다른 요소들에 의해 영향을 받을 수 있습니다. 예를 들어, 데이터베이스 서버의 부하 상황이나 네트워크 대역폭 등의 요소들은 실제 실행 속도에 영향을 줄 수 있습니다.

 따라서 COST는 쿼리 실행 계획을 최적화하는데 도움을 주는 지표이지만, 실제 실행 속도에 대한 정확한 예측을 제공하지는 않습니다. 따라서 COST를 참고하여 최적의 실행 계획을 선택하되, 실제 실행 결과를 확인하여 성능을 평가하는 것이 중요합니다.

 

 


실제 실행 결과에서 Cost를 확인하는 방법은 다음과 같습니다.

 

실행 계획 확인

 먼저, 실행 계획을 확인하여 각 단계의 비용을 확인할 수 있습니다. 실행 계획은 EXPLAIN PLAN 명령을 사용하여 확인할 수 있습니다. 예를 들어, 다음과 같이 실행 계획을 확인할 수 있습니다.

EXPLAIN PLAN FOR <쿼리>;


SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

위의 쿼리를 실행하면 실행 계획이 출력되며, 각 단계의 비용(COST)도 함께 표시됩니다.

 

실행 시간 측정

 쿼리를 실행하여 실제 실행 시간을 측정할 수 있습니다. 이를 위해 SET TIMING ON 명령을 사용하여 실행 시간을 측정할 수 있습니다. 예를 들어, 다음과 같이 실행 시간을 측정할 수 있습니다.

SET TIMING ON;
SELECT * FROM 테이블 WHERE 조건;
위의 쿼리를 실행하면 쿼리의 실행 시간이 출력됩니다. 이를 통해 쿼리의 실행 속도를 확인할 수 있습니다.


실제 실행 결과에서 코스트를 확인하는 것은 예상 비용과 실제 실행 속도를 비교하여 최적의 실행 계획을 선택하는 데 도움을 줍니다. 예를 들어, 예상 비용이 낮은 실행 계획이 선택되었지만, 실제 실행 시간이 오래 걸린다면 다른 실행 계획을 고려해볼 수 있습니다. 이를 통해 쿼리의 성능을 개선할 수 있습니다.

 

실제 현장에서의 EXPAIN PLAN 결과 값

Plan hash value: 3275518041
 
-------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                      |     1 |   448 |  2372   (1)| 00:00:29 |
|   1 |  TABLE ACCESS BY INDEX ROWID         | TABLE_B               |     1 |    16 |     3   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN                  | PK_TABLE_B            |     1 |       |     2   (0)| 00:00:01 |
|   3 |  TABLE ACCESS BY INDEX ROWID         | TABLE_G                |     1 |    11 |     1   (0)| 00:00:01 |
|*  4 |   INDEX UNIQUE SCAN                  | PK_TABLE_G             |     1 |       |     0   (0)| 00:00:01 |
|*  5 |  COUNT STOPKEY                       |                      |       |       |            |          |
|   6 |   NESTED LOOPS                       |                      |     1 |   448 |  2153   (1)| 00:00:26 |
|   7 |    NESTED LOOPS                      |                      |     1 |   363 |  2151   (1)| 00:00:26 |
|   8 |     NESTED LOOPS                     |                      |     1 |   333 |  2150   (1)| 00:00:26 |
|   9 |      NESTED LOOPS                    |                      |     1 |   313 |  2148   (1)| 00:00:26 |
|  10 |       NESTED LOOPS                   |                      |   512 | 21504 |  1123   (0)| 00:00:14 |
|* 11 |        TABLE ACCESS BY INDEX ROWID   | TABLE_F             |   512 |  5632 |    99   (0)| 00:00:02 |
|* 12 |         INDEX RANGE SCAN             | PK_TABLE_F          |   184 |       |     8   (0)| 00:00:01 |
|  13 |          SORT AGGREGATE              |                      |     1 |     4 |            |          |
|  14 |           INDEX FULL SCAN (MIN/MAX)  | PK_TABLE_F          |     1 |     4 |     2   (0)| 00:00:01 |
|* 15 |        TABLE ACCESS BY INDEX ROWID   | TABLE_C              |     1 |    31 |     2   (0)| 00:00:01 |
|* 16 |         INDEX RANGE SCAN DESCENDING  | PK_TABLE_C        |     1 |       |     1   (0)| 00:00:01 |
|* 17 |       TABLE ACCESS BY INDEX ROWID    | TABLE_D          |     1 |   271 |     2   (0)| 00:00:01 |
|* 18 |        INDEX UNIQUE SCAN             | PK_TABLE_D       |     1 |       |     1   (0)| 00:00:01 |
|  19 |         SORT AGGREGATE               |                      |     1 |    10 |            |          |
|* 20 |          FILTER                      |                      |       |       |            |          |
|  21 |           FIRST ROW                  |                      |     1 |    10 |     3   (0)| 00:00:01 |
|* 22 |            INDEX RANGE SCAN (MIN/MAX)| I_TABLE_D_TABLE_C_KEY |     1 |    10 |     3   (0)| 00:00:01 |
|* 23 |      TABLE ACCESS BY INDEX ROWID     | TABLE_A               |     1 |    20 |     2   (0)| 00:00:01 |
|* 24 |       INDEX RANGE SCAN DESCENDING    | PK_TABLE_A            |     1 |       |     1   (0)| 00:00:01 |
|  25 |     TABLE ACCESS BY INDEX ROWID      | TABLE_E             |     1 |    30 |     1   (0)| 00:00:01 |
|* 26 |      INDEX RANGE SCAN DESCENDING     | PK_TABLE_E       |     1 |       |     0   (0)| 00:00:01 |
|* 27 |    TABLE ACCESS BY INDEX ROWID       | TABLE_B               |     1 |    85 |     2   (0)| 00:00:01 |
|* 28 |     INDEX UNIQUE SCAN                | PK_TABLE_B            |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("B"."TABLE_B_KEY"=:B1)
   4 - access("TABLE_G__KEY"=:B1)
   5 - filter(ROWNUM<=100)
  11 - filter("F"."FLAG"='N' AND "F"."LOCAL_KEY"=1)
  12 - access("F"."TABLE_F_KEY" > (SELECT MAX("TABLE_F_KEY") FROM "TABLE_F" "TABLE_F"))
  15 - filter("C"."FLAG"='Y')
  16 - access("F"."TABLE_C_KEY"="C"."TABLE_C_KEY")
       filter("F"."TABLE_C_KEY"="C"."TABLE_C_KEY")
  17 - filter("C"."TABLE_C_KEY"="T"."TABLE_C_KEY")
  18 - access("T"."TABLE_D_KEY"= (SELECT MAX("X"."TABLE_D_KEY") FROM "TABLE_D" "K" WHERE 
              :B1='Y' AND "K"."TABLE_C_KEY"=:B2))
  20 - filter(:B1='Y')
  22 - access("X"."TABLE_C_KEY"=:B1)
  23 - filter("A"."TABLE_B_KEY" IS NOT NULL AND "A"."FLAG"='Y' AND "A"."LOCAL_KEY"=2023)
  24 - access("C"."TABLE_A_KEY"="A"."TABLE_A_KEY")
       filter("C"."TABLE_A_KEY"="A"."TABLE_A_KEY")
  26 - access("A"."TABLE_E_KEY"="E"."TABLE_E_KEY")
       filter("A"."TABLE_E_KEY"="E"."TABLE_E_KEY")
  27 - filter("B"."TEMPORARY_VALUE" IS NOT NULL AND "B"."FLAG"='Y')
  28 - access("A"."TABLE_B_KEY"="B"."TABLE_B_KEY")

 

 

[오라클] 오라클 쿼리 튜닝 예시 (Oracle Query Tuning Example)

 

[오라클] 오라클 쿼리 튜닝 예시 (Oracle Query Tuning Example)

[오라클] 쿼리 튜닝 예시 (Oracle Query Tuning Example) #나 자신을 위한 메모 오라클 쿼리 튜닝은 데이터베이스 성능을 향상시키기 위해 쿼리 실행 계획을 최적화하는 과정입니다. 다음은 오라클 쿼리

trivia-korea.tistory.com

 

300x250