레이블이 옵티마이저인 게시물을 표시합니다. 모든 게시물 표시
레이블이 옵티마이저인 게시물을 표시합니다. 모든 게시물 표시

2021년 12월 23일 목요일

오라클 옵티마이저 통계정보, DBMS_STATS, 테이틀/컬럼/인덱스 통계정보, 오라클교육, ORACLE동영상교육, 자바학원, 오라클학원,JAVA학원

 

오라클 옵티마이저 통계정보, DBMS_STATS, 테이틀/컬럼/인덱스 통계정보, 오라클교육, ORACLE동영상교육, 자바학원, 오라클학원,JAVA학원


https://youtu.be/eCAjkWShhe4

https://www.youtube.com/watch?v=eQmUdTkIDm8&list=PLxU-iZCqT52DFRbLFQIgGUFp-5En2DYRG&index=34 

https://www.youtube.com/watch?v=SYUxsqhzNRQ&list=PLxU-iZCqT52DFRbLFQIgGUFp-5En2DYRG&index=33 

https://www.youtube.com/watch?v=CK4UzRwkDVs&list=PLxU-iZCqT52DFRbLFQIgGUFp-5En2DYRG&index=32 

https://www.youtube.com/watch?v=9rvdwAcz4D0&list=PLxU-iZCqT52DFRbLFQIgGUFp-5En2DYRG&index=31 

https://www.youtube.com/watch?v=2DjEl1PYzWo&list=PLxU-iZCqT52DFRbLFQIgGUFp-5En2DYRG&index=30 


옵티마이저 통계정보


DBMS_STATS

테이블, 컬럼 통계정보




DBMS-STATS를 알아보기 전에 테이블 및 컬럼의 통계정보가 무엇인지 알아보도록 하겠습니다.


[실습]

사원(EMP) 테이블은 14개의 행이 있고 테이블 통계정보와 컬럼 통계정보가 생성되어 있습니다. USER_TAB_COL_STATISTICS에는 컬럼의 통계정보(유일한 값의수, LOW/HIGH VALUE, DENSITY, 버켓의 수, 널 값의 수, 컬럼값의 평균길이, 히스토그램생성여부)가, USER_TAB_STATISTICS에는 테이블에 대한 통계정보(행의수, 블록수, 평균레코드길이)가 생성되어 있는데요 확인해 보겠습니다.

EMP 테이블은 14건 이고 컬럼의 통계정보를 조회하면 다음과 같습니다.



NUM_DISTINCT 값은 유일한 값의 수 입니다.

density(밀도)는 컬럼값을 하나의 조건으로 등호(=)로 검색시 선택도를 나타내는데,  histogram을 사용할 수 없는 경우(값의 출현빈도를 고려하지않은 경우) 컬럼에 존재하는 값이 한가지라면 1 이고 5가지이면 0.2가 되는데, 이값은 1/NUM_DISTINCT 입니다. 물론 출현빈도를 고려한 histogram이 있는 경우 density는 오라클에서 알아서 생성을 합니다.

histogram이란 컬럼값의 출현빈도, 분포/분산정도를 그래피컬하게 나타낸 것이며 값의 분포가 특정값에 치우치는 경우 히스토그램을 이용해서 정확한 예상 레코드 건수(Cardinality)를 측정 가능 합니다.





histogram은 컬럼의 값이 Skew 되어 있을때 특히 장점이 있는데, 컬럼값이 Skew 되었다는 것은 값의 출현빈도가 특정 값에 몰려있다는 이야기 입니다. histogram이 없다면 Cardinality 계산이  맞지 않을 것 입니다.

histogram값이 frequence인 경우는 값별로 빈도수를 저장하는 도수분포 히스토그램을 뜻하며 값의수 = 버킷수 입니다.

histogram을 이용하여 옵티마이저는 더 정확한 카디널리티를 추정하고 정확한 실행을 생성할 수 있습니다

NUM_BUCKETS 값은 열에 대한 히스토그램 버켓수(값을 담는 바구니)로 histogram이 있는 경우 NUM_DISTINCT 값이며 없는 경우 1 입니다. deptno 컬럼의 경우 buckets 값은 3 입니다.

EMP 테이블은 14건이 있고 직무(JOB) 컬럼은 CLERK, SALESMAN, MANAGER, PRESIDENT, ANALYST 5종류의 값을 가지고 있습니다. 
job컬럼은 유일한 값의 종류가 5이고, 그러므로 density가 0.2이고 histogram 이 없습니다. 모든 컬럼값들의 출현빈도가 동일하다고 가정을 하는데요, 그래서 아래처럼 예측건수와 실제건수가 차이가 날수 있다는것 입니다.
Cardinality는 WHERE절의 조건( predicate)에 의해서 추출되는 행의 수를 의미합니다.
job 컬럼의 Cardinality는 predicate가 하나(where절의 조건이 하나면)면 선택도(Selectivity)가 density와 같은 의미로 생각되어 NUM_ROWS * DENSITY = 14 * 0.2 = 2.8 정도 되는데, 사실 Cardinality는 NUM_ROWS * 선택도(Selectivity) 입니다. 컬럼의 값들이 WHERE절에서 AND, OR 로 엮이면 선택도가 변하게 됩니다. 정확한 Cardinality 예상은 최적의 실행계획을 만드는데 중요한 요인입니다.

다음은 EMP 테이블의 테이블통계정보를 조회한 내용입니다.

SELECT OBJECT_TYPE, NUM_ROWS, BLOCKS, 
               AVG_ROW_LEN 
FROM    USER_TAB_STATISTICS
WHERE TABLE_NAME = 'EMP';

OBJECT_TYPE                NUM_ROWS     BLOCKS   AVG_ROW_LEN
—--------------------------------------------------------------------------------------------
TABLE                                     14                         5                 42


  • 오라클의 Analyze 명령, DBMS_UTILITY, DBMS-STATS 등을 이용하여 옵티마이저 통계정보를 생성할 수 있는데 DBMS-STATS 사용을 권장하고 있습니다.
  • 옵티마이저 통계정보는 데이터베이스 모든 오브젝트에 대한 자료를 모아 기술한 통계인데 데이터 딕셔너리(Data Dictionary)에 저장되며 오라클 옵티마이저는 이 통계정보를 바탕으로 효율적인 SQL 실행계획을 만들어 냅니다. 물론 생성한 통계정보를 지정한 별도의 테이블에 저장 할 수도 있습니다.
  • DBMS_STATS 패키지는 SQL 성능을 향상 시키기 위해 Optimizer Statistics(옵티마이저 통계정보)를 수집합니다.
  • 오라클은 테이블이나 인덱스와 같은 데이터베이스 오브젝트에 대한 통계 정보 생성, 삭제, 익스포트, 임포트를 용이하게 하기 위해 DBMS_STATS 패키지를 제공하는데 이 패키지를 이용하면 테이블이나 인덱스의 모든 데이터를 근간으로 통계 정보를 생성할 수 있습니다.
  • 대용량의 테이블이라면 모든 데이터를 가지고 액세스 경로를 추측하는 것보다 샘플링 데이터를 가지고 추측하는 것이 훨씬 용이하다. 대체로 샘플링 데이터는 5% 이하로 ROW나 BLOCK에 만들며 DBMS_STATS 패키지의 automatic sampling 프로시저를 이용하면 됩니다.
  • 통계정보 수집용 별도의 테이블 생성은 DBMS_STATS 패키지의 create_stat_table 프로시저를 이용하여 만들면 됩니다.
  • DBMS_STATS 패키지에는 몇 개의 유용한 프로시저가 있는데 아래와 같습니다.

gather_database_ stats: 데이터베이스의 모든 Object에 대한 통계 정보 생성.

      gather_system_stats :  CPU, I/O등 시스템 Performance 통계정보 생성

gather_dictionary_ statsSYSSYSTEM 스키마의 Object에 대한 통계 정보 생성.

gather_schema_ stats: 해당 스키마의 모든 Object에 대한 통계 정보 생성.

gather_table_stats : 테이블과 그 테이블과 연관된 인덱스에 대한 통계 정보 생성.

gather_index_stats : 인덱스에 대해 통계 정보를 생성.


-- 여기에서 사용된 인자는 접속한 계정, 통계정보 수집용 테이블 이름, 테이블스페이스 이름이다.

-- 사용자 스키마에 통계정보를 보유할 stat_tab 이라는 이름의 테이블을 생성하며 

-- 이 테이블의 컬럼과 타입은 DBMS_STAT 패키지를 통해서만 접근되어야 합니다.

SQL> execute dbms_stats.create_stat_table(USER, 'stat_tab');

PL/SQL 처리가 정상적으로 완료되었습니다.


-- 현재 로그온한 스키마 계정의 OBJECT 대해 통계 정보를 생성합니다.

SQL> execute dbms_stats.gather_schema_stats(ownname => USER);

PL/SQL 처리가 정상적으로 완료되었습니다.


-- 현재 로그온한 스키마 계정의 EMP 테이블에 대해 통계 정보를 생성합니다.

SQL>  execute dbms_stats.gather_table_stats(USER, 'emp');

PL/SQL 처리가 정상적으로 완료되었습니다.


-- 데이터 딕셔너리에서 생성된 통계정보 확인, LAST_ANALYZED 칼럼을 확인하세요.

SQL>SELECT *  FROM USER_TABLES WHERE TABLE_NAME = ‘EMP’;


--EMP 테이블의 통계정보를 생성하면서 연관된 인덱스의 통계정보도 생성

SQL>exec dbms_stats.gather_table_stats(← 테이블 통계정보 생성.

 USER, ‘emp’',

cascade => true);  ← 테이블의 각 인덱스에서 GATHER_INDEX_STATS 프로시저를 실행하는 것과 같습니다. 


--EMP 테이블 및 컬럼 및 연관 인덱스의 통계정보를 생성

--for all columns size 1 : 모든 컬럼의 통계정보를 생성하는데 컬럼 내에 존재하는 여러 가지 값들의 출현빈도, 값의 분포를 모두 동일한 값 1로 간주, 즉 histogram 을 사용하지 않는  것이며, where 조건에 들어오는 특정 컬럼에 대한 값의 변화에 따라서 실행계획이 변경될 가능성을 없다는 뜻입니다.

-- method_opt의 기본값은 for all columns size auto로 컬럼값의 출현빈도인 histogram 생성을 오라클이 알아서 합니다.

SQL>exec dbms_stats.gather_table_stats(

               USER, 'emp',

cascade => true,

method_opt => ‘for all column size 1’);  


--EMP 테이블과 인덱스 컬럼의 통계정보를 생성(모든 컬럼의 통계정보가 생성되는 것은아님)

SQL>exec dbms_stats.gather_table_stats(

               USER, 'emp',

              method_opt => ‘for all indexed columns’’);  


--EMP테이블의 15%의 행을 가지고 테이블, 컬럼, 연관된 인덱스의 통계정보를 생성

--method_opt의 기본값은 “FOR ALL COLUMNS SIZE AUTO”으로 테이블 통계정보 생성할 때 컬럼의 통계정보도 생성을 하는데  Histogram 의 생성여부를 오라클이 알아서  합니다.

SQL>exec dbms_stats.gather_table_stats(

               USER, 'emp',

cascade => true,

estimate_percent=>15);  


--EMP 테이블의 테이블, 컬럼의 통계정보를 생성(연관된 인덱스의 통계정보, histogram 생성안함)

SQL>exec dbms_stats.gather_table_stats(

               USER, 'myemp1',

               method_opt => ‘for all columns size 1’);  


-- 현재 EMP 테이블의 통계정보를 STAT_TAB으로 EXPORT

SQL> execute dbms_stats.export_table_stats (USER, 'emp',null,'stat_tab');

PL/SQL 처리가 정상적으로 완료되었습니다.


-- 딕셔너리와 STAT_TAB의 통계정보의 차이를 비교, 현재는 차이가 없다.

SQL> select * from table(dbms_stats.diff_table_stats_in_stattab(USER,'emp','stat_tab'));


REPORT                                                          MAXDIFFPCT

-------------------------------------------------------------------------------- ----------

###################################################           0


-- 통계정보 수집용 테이블 삭제

SQL> execute dbms_stats.drop_stat_table(USER,'stat_tab');

PL/SQL 처리가 정상적으로 완료되었습니다.


이번에는 시스템과 관련된 통계 정보를 생성해 보겠습니다.


DBMS_STATS를 이용하여 CBO(cost based optimizer)에게 system performance 통계정보를 제공 할 수 있는데 이 패키지는 CPU 사용과 I/O 퍼센트 등의 정보를 통계정보 생성시 추가한다. dbms_stats.gather_system_stats 프로시저를 이용하고 파라미터는 다음과 같다.


Gathering_mode : 통계 정보에 대한 수집을 특정한 시기 또는 기간에 하는 경우에는 interval 이나 start/stop 값을 주면 되고 noworkload라고 하면 시스템은 통계 정보를 general하게 수집한다.

Interval : Gathering_mode에서 interval이라고 한 경우에만 사용한다.

Stattab : 시스템의 통계 정보가 모아질 테이블을 기술한다.

Statown : 시스템의 통계 정보가 모아질 테이블의 Owner를 기술한다. (현재 패키지를 실행 할 Schema와 다를 경우에 기술)


SQL> begin

    dbms_stats.gather_system_stats (

       gathering_mode => 'interval',

     interval => 60,   //분단위

     stattab => 'stat_tab',

       statown => USER);

    end;

  /


PL/SQL 처리가 정상적으로 완료되었습니다.


DBMS_STATS.gather_system_stats를 사용하기 전에 job_queue_processes 매개변수를 SET 시켜야 하는데 기본값은 0, 양수값으로 세팅해야 한다. 그렇지 않으면 gather_system_stats 프로시저가 동작하지 않을 수 있다. 현재 세션에서 이 값을 다이나믹하게 설정하려면 alter system set job_queue_processes = 20 이라고 하면 된다.


이상에서 설명드린 부분외에 일한 통계정보를 DBMS_STATS 패키지에서 자동으로 생성하는 방법도 있지만 본 강좌에서는 설명드리지는 않겠습니다.


#오라클, #옵티마이저, #통계정보, #DBMS_STATS, #테이틀통계정보, #컬럼통계정보, #옵티마이저통계정보, #오라클교육, #ORACLE동영상, #ORACLE교육, #오라클학원, #ORACLE학원, 오라클, 옵티마이저, 통계정보, DBMS_STATS, 테이틀통계정보, 컬럼통계정보, 옵티마이저통계정보, 오라클교육, ORACLE동영상, ORACLE교육, 오라클학원, ORACLE학원, 
 

오라클 옵티마이저 모드, optimizer_mode, all_rows, first_rows, rule, choose, 오라클교육동영상, SQL튜닝동영상, 오라클학원, 오라클교육, ORACLE학원, ORACLE동영상교육, SQL튜닝



오라클 옵티마이저 모드, optimizer_mode, all_rows, first_rows, rule, choose, 오라클교육동영상, SQL튜닝동영상, 오라클학원, 오라클교육, ORACLE학원, ORACLE동영상교육, SQL튜닝


http://ojc.asia/bbs/board.php?bo_table=LecOracle&wr_id=305

이미지 썸네일 삭제
오라클 옵티마이저 모드, optimizer_mode, all_rows, first_rows, rule, choose, 오라클동영상, SQL튜닝동영상

오라클 옵티마이저 모드, optimizer_mode, all_rows, first_rows, rule, choose, 오라클동영상, SQL튜닝동영상옵티마이저 모드초기화 파라미터 Optimizer_ModeORACLE 19COptimizer Statistics(테이블 or 컬럼 통계정보)?테이블 통계정보는 데이터 건수, 블록의 수, 레코드의 평균 길이, 마지막…

ojc.asia







오라클 옵티마이저 모드, optimizer_mode, all_rows, first_rows, rule, choose, 오라클동영상, SQL튜닝동영상



옵티마이저 모드



초기화 파라미터 Optimizer_Mode



ORACLE 19C





Optimizer Statistics(테이블 or 컬럼 통계정보)?


  • 테이블 통계정보는 데이터 건수, 블록의 수, 레코드의 평균 길이, 마지막 통계정보 생성일자  등이다. 이러한 통계정보를 이용하여 옵티마이저는 실행계획상의 다양한 연산(Operations) 비용(Cost)을 다른 통계정보를 바탕으로 산정하며 오퍼레이션마다 추출되는 로우(ROW, RECORD)의 수를 예측 합니다.


  • 테이블 또는 칼럼의 통계정보는 USER_TAB_STATISTICS, USER_TAB_COL_STATISTIC, USER_TABLES, USER_TAB_COLUMNS와 같은 딕셔너리 뷰에서 확인할 수 있습니다.


  • 풀 테이블 스캔시 테이블 액세스의 비용(COST)은 DB_FILE_MULTIBLOCK_READ_COUNT 파라미터와 테이블의 데이터 블록 수를 이용하여 계산을 하게 된다. 이 파라미터는 Full Scan(Full Table Scan, Index Fast Full Scan) 수행 시 한번에 읽어 들일 Block 수를 결정하며 Full Scan의 성능을 제어하는 목적으로 사용된다. System Statistics가 있다면 이 파라미터는 고려대상이 아니며 없는 경우 이 파라미터 값을 기준으로 Full Scan을 수행 합니다.


SQL> show parameter DB_FILE_MULTIBLOCK_READ_COUNT


NAME                            TYPE     VALUE

-----------------------------------------------------------------------

db_file_multiblock_read_count      integer     128


  • 칼럼 통계정보는 칼럼의 DISTINCT VALUES의 수(NUMBER OF DISTINCT VALUES, NDV), 칼럼의 최소값, 최대값과 같은 정보를 가지고 있습니다.


  • 옵티마이저는 테이블 통계정보(데이터 건수등)와 결합하여 SQL의 오퍼레이션에서 리턴되는 로우 수(레코드 건수)를 예측 합니다. 






ORACLE 초기화 파라미터인 OPTIMIZER_MODE는 오라클 옵티마이저 최적의 Access 경로를 선택하는 기본 설정이 됩니다. 즉 옵티마이저가 어떠한 기준으로 최적화된 Access 경로를 추출하는지 결정하는 방법에 대해 제시한다고 볼 수 있습니다. 



초기화 파라미터 Optimizer_Mode?


[문서로 지원하는것]

ALL_ROWS : 테이블의 통계 정보의 유무와 상관없이 모든 SQL 문에 대해 CBO(Cost Based Optimizer, 비용기반 옵티마이저)를 이용하며 최대 처리량을 목표로 한다. 최대 처리량을 목표로 한다는 것은 전체 SQL문의 결과를 완료하는데 걸리는 시간이 적게 드는 것을 목표로 한다는 것 입니다. (Oracle19C의 기본값으로 테이블에 대한 통계정보가 없더라도 CBO로 동작된다.)

FIRST_ROWS_(1|10|100|1000): 통계 정보의 유무와 상관없이 모든 SQL 문에 대해 CBO를 이용하며 처음 N개의 레코드를 가장 빨리 추출할 수 있는 최적의 실행 경로를 찾습니다.

 FIRST_ROWS: 옵티마이저는 첫 번째 레코드의 추출을 가장 빠르게 하는 최적의 실행경로를 찾습니다.


[문서로 지원하지 않지만 사용은 가능한것]

RULE : 통계정보의 유무와 관계 없이 모든 SQL에 대해 RBO를 사용하도록 한다. Oracle10g R2 이후 더 문서로 이상 지원은 하지 않지만 사용은 가능하다. RBO에서 CBO로 마이그레이션을 위해 아직까지 사용은 가능하지만 언젠가는 없어지므로 RBO를 사용하고 있다면 CBO로 전환이 필요하다.


CHOOSE : 오라클 옵티마이저는 CBO(Cost-Based Optimizer)와 RBO(Rule-Based Optimizer)중 하나를 선택한다. 통계 정보의 이용가능 여부에 따라 결정하는데 통계정보가 이용 가능하면 CBO를 사용하고 불가능한 경우에는 RBO를 사용한다. 만약 데이터딕셔너리에 액세스 되는 테이블 중 적어도 하나의 테이블에 대한 통계 정보가 있는 경우엔 CBO를 사용하며 최대 처리량(ALL_ROWS)을 목표로 최적화를 수행한다.


딕셔너리에 약간의 통계 정보만을 가지고 있다면 CBO가 사용될 수 있지만 옵티마이저는 통계 정보가 없는 부분에 대해서는 통계 정보를 추측해야 하며 이는 최선의 실행 계획이라기보다 차선의 실행 계획이라고 볼 수 있다. 


만약 Access되는 테이블에 대한 통계 정보가 하나도 없다면 RBO를 사용한다.


오라클 11g 에서는 지난 방식이지만 지원은 하고 있다. 문서로는 지원하지 않지만 여전히 사용은 가능한 방식이다.



초기 매개 변수 파일(init.ora)에서 위의 파라미터를 변경할 수도 있으며 alter session set optimizer_mode, alter system set 명령을 이용할 수도 있다. 또한 명령 행에서 Oracle Hint 구문을 이용하여 Optimizer Mode를 변경하는 것도 가능 합니다. 


[힌트 사용 형식]

/*+ CHOOSE */

/*+ RULE */

/*+ ALL_ROWS */

/*+ FIRST_ROWS_[(n)] */  

주의 : FIRST_ROWS 힌트와 집합함수를 같이 사용하면 FIRST_ROWS 힌트는 무시된다.


결국 힌트는 개별 SQL문에 대해 CBO의 목표를 설정하기 위해 사용하는 것이다. 각 SQL문에서 힌트를 사용하게 되면 초기 파라미터에서 설정한 것보다 우선 적용 됩니다.


SQL> show parameter optimizer_mode

NAME                                 TYPE        VALUE

------------------------------------ ----------- -----------------

optimizer_mode                       string      CHOOSE


SQL> alter session set optimizer_mode = first_rows_1;

세션이 변경되었습니다.


SQL> show parameter optimizer_mode

NAME                                 TYPE        VALUE

------------------------------------ ----------- 

optimizer_mode                       string      FIRST_ROWS_1


-- 설정할 수 없는 값을 주면 현재 시스템에서 사용 가능한 옵티마이저 모드를 확인할 수있다.

SQL> alter session set optimizer_mode = very_very_fast;

ERROR:

ORA-00096: 부적당한 VERY_VERY_FAST 값이 optimizer_mode 매개변수에 있고, first_rows_1000, first_rows_100, first_rows_10, first_rows_1, first_rows, all_rows, choose, rule의 사이에 있어야 합니다


옵티마이저 모드에 따라서 만들어지는 실행계획이 달라지므로 성능에 영향을 미칩니다.


CBO가 사용하는 통계 정보는 데이터 딕셔너리에 저장되며 DBMS_STATS 패키지나 ANALYZE 명령을 이용하여 스키마 객체에 대한 데이터의 분포도 등을 구할 수 있다. SQL문을 구사하면서 최적화된 CBO의 사용을 위해서는 반드시 통계 정보를 생성해야 합니다.



Optimizer Mode Setting 방법


  1. Instance 수준의 셋팅 방법


  • 예) OPTIMIZER_MODE=FIRST_ROWS


  1. Session/System 수준의 셋팅 방법


예) alter session set optimizer_mode=rule과 같이 정의하면 해당 세션이 끝나기 전까지는 규칙 기반(RULE-BASED) 옵티마이저 모드를 이용하게 된다.


예) alter system set optimizer_mode=first_rows과 같이 정의하면 전체 오라클 시스템에서 FIRST_ROWS 옵티마이저 모드를 이용하게 된다.


  1. Statement 수준의 셋팅 방법


예) SELECT /*+ FIRST_ROWS */

ENAME,

SAL,

JOB

           FROM EMP

           WHERE SAL > (SELECT MAX(SAL)

                           FROM  EMP

                           WHERE DEPTNO = 10) 



[실습]


Oracle Trigger를 이용하여 SCOTT 계정으로 접속하는 모든 사용자들의 Optimizer_Mode를 ALL_ROWS로 변경하세요. 

CREATE OR REPLACE TRIGGER Tr_setOptimizerMode
AFTER LOGON
ON DATABASE
BEGIN
 IF USER LIKE 'SCOTT%' THEN
 EXECUTE IMMEDIATE 'alter session set optimizer_mode=all_rows';
 END IF;
END;
/







[실습]


동일한 쿼리문에 대해 Optimizer_Mode를  FIRST_ROWS, ALL_ROWS 변경한 후 실행계획 및 통계정보를 확인하고 SQL 성능에 대해 고려해 보세요.

2000만건 있는 사원테이블과 7건 있는 부서테이블을 조인하여 전체사원의 사원명, 부서명을 추출 합니다.

SQL> set autotrace traceonly;
SQL> set timing on
SQL> ALTER SESSION SET OPTIMIZER_MODE=ALL_ROWS;

세션이 변경되었습니다.

경   과: 00:00:00.00
SQL> SELECT  E.EMPNO, E.ENAME, D.DNAME
  2   FROM  MYEMP1 E, MYDEPT1 D
  3  WHERE  E.DEPTNO = D.DEPTNO;

20000004 행이 선택되었습니다.

경   과: 00:02:00.50

Execution Plan
----------------------------------------------------------
Plan hash value: 2850841177

------------------------------------------------------------------------------
| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |    20M|   839M| 56045   (1)| 00:00:03 |
|*  1 |  HASH JOIN         |         |    20M|   839M| 56045   (1)| 00:00:03 |
|   2 |   TABLE ACCESS FULL| MYDEPT1 |     7 |   126 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| MYEMP1  |    20M|   495M| 55890   (1)| 00:00:03 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("E"."DEPTNO"="D"."DEPTNO")


Statistics
----------------------------------------------------------
          8  recursive calls
          0  db block gets
    1521008  consistent gets
          0  physical reads
          0  redo size
  966344349  bytes sent via SQL*Net to client
   14667112  bytes received via SQL*Net from client
    1333335  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
   20000004  rows processed


—----------------------------------------------------------------------------------------------------

SQL> ALTER SESSION SET OPTIMIZER_MODE=FIRST_ROWS;

세션이 변경되었습니다.

경   과: 00:00:00.00
SQL> SELECT  E.EMPNO, E.ENAME, D.DNAME
  2   FROM  MYEMP1 E, MYDEPT1 D
  3  WHERE  E.DEPTNO = D.DEPTNO;

20000004 행이 선택되었습니다.

경   과: 00:02:04.53

Execution Plan
----------------------------------------------------------
Plan hash value: 3661616267

--------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                   |    20M|   839M|   866K  (1)| 00:00:34 |
|   1 |  NESTED LOOPS                |                   |    20M|   839M|   866K  (1)| 00:00:34 |
|   2 |   NESTED LOOPS               |                   |    35M|   839M|   866K  (1)| 00:00:34 |
|   3 |    TABLE ACCESS FULL         | MYDEPT1           |     7 |   126 |     3   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN          | IDX_MYEMP1_DEPTNO |  5000K|       |  9384   (1)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| MYEMP1            |  2857K|    70M|   209K  (1)| 00:00:09 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("E"."DEPTNO"="D"."DEPTNO")


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
    3449522  consistent gets
          0  physical reads
          0  redo size
  822344313  bytes sent via SQL*Net to client
   14667112  bytes received via SQL*Net from client
    1333335  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
   20000004  rows processed



[실습]


이번에는 처음 10개만 가져오기 위해 인라인뷰, ROWNUM을 이용하여 작성한 쿼리 입니다. ALL_ROWS와 FIRST_ROWS에 따라 생성되는 실행계획 및 통계정보를 확인하세요.  통계정보의 consistent gets 에서 SELECT시 읽어 들이는 블록 수를 확인해보세요, 읽어들이는 블록이 수가 적을수록 좋은 실행계획 입니다.


ALTER SESSION SET OPTIMIZER_MODE=ALL_ROWS;

SELECT *
FROM (
SELECt ROWNUM RNUM, T.*
    FROM (
        SELECT E.EMPNO, E.ENAME, D.DNAME
         FROM  MYEMP1 E, MYDEPT1 D
        WHERE  E.DEPTNO = D.DEPTNO
        ) T    )
WHERE RNUM >= 1
AND   RNUM <= 10;

10 행이 선택되었습니다.

경   과: 00:00:04.69

Execution Plan
----------------------------------------------------------
Plan hash value: 3222485226

--------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |         |    20M|  2479M| 56045   (1)| 00:00:03 |
|*  1 |  VIEW                |         |    20M|  2479M| 56045   (1)| 00:00:03 |
|   2 |   COUNT              |         |       |       |            |          |
|*  3 |    HASH JOIN         |         |    20M|   839M| 56045   (1)| 00:00:03 |
|   4 |     TABLE ACCESS FULL| MYDEPT1 |     7 |   126 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| MYEMP1  |    20M|   495M| 55890   (1)| 00:00:03 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RNUM"<=10 AND "RNUM">=1)
   3 - access("E"."DEPTNO"="D"."DEPTNO")


Statistics
----------------------------------------------------------
          5  recursive calls
          0  db block gets
     200314  consistent gets
          0  physical reads
          0  redo size
       1193  bytes sent via SQL*Net to client
        573  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         10  rows processed


ALTER SESSION SET OPTIMIZER_MODE=FIRST_ROWS;

first_rows는 한건만 가지고 오는데 있어 가장 효율적인 실행계획을 만드는 옵티마이저 모드이므로 메모리에 전체 테이블을 올려서 조인하는 해시조인, 머지조인보다는 중첩루프 조인을 선호하게 됩니다.

SELECT *
FROM (
SELECt ROWNUM RNUM, T.*
    FROM (
        SELECT E.EMPNO, E.ENAME, D.DNAME
         FROM  MYEMP1 E, MYDEPT1 D
        WHERE  E.DEPTNO = D.DEPTNO
        ) T
    )
WHERE RNUM >= 1
AND   RNUM <= 10;


경   과: 00:00:08.46

Execution Plan
----------------------------------------------------------
Plan hash value: 686395518

----------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |    20M|  2479M|   866K  (1)| 00:00:34 |
|*  1 |  VIEW                          |                   |    20M|  2479M|   866K  (1)| 00:00:34 |
|   2 |   COUNT                        |                   |       |       |            |          |
|   3 |    NESTED LOOPS                |                   |    20M|   839M|   866K  (1)| 00:00:34 |
|   4 |     NESTED LOOPS               |                   |    35M|   839M|   866K  (1)| 00:00:34 |
|   5 |      TABLE ACCESS FULL         | MYDEPT1           |     7 |   126 |     3   (0)| 00:00:01 |
|*  6 |      INDEX RANGE SCAN          | IDX_MYEMP1_DEPTNO |  5000K|       |  9384   (1)| 00:00:01 |
|   7 |     TABLE ACCESS BY INDEX ROWID| MYEMP1            |  2857K|    70M|   209K  (1)| 00:00:09 |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RNUM"<=10 AND "RNUM">=1)
   6 - access("E"."DEPTNO"="D"."DEPTNO")


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
     836392  consistent gets
          0  physical reads
          0  redo size
       1115  bytes sent via SQL*Net to client
        574  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         10  rows processed



#오라클, #옵티마이저, #optimizer, #optimizer_mode, #all_rows, #first_rows, #rule, #choose, #오라클동영상, #SQL튜닝, #SQL동영상, #오라클학원, #ORACLE학원, #ORACLE교육, #오라클교육, 오라클, 옵티마이저, optimizer, optimizer_mode, all_rows, first_rows, rule, choose, 오라클동영상, SQL튜닝, SQL동영상, 오라클학원, ORACLE학원, ORACLE교육, 오라클교육, 
 



(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...