레이블이 SQL튜닝인 게시물을 표시합니다. 모든 게시물 표시
레이블이 SQL튜닝인 게시물을 표시합니다. 모든 게시물 표시

2021년 12월 31일 금요일

오라클동영상,FORALL 기반 벌크 입력(BULK INSERT) 실습, DMLL성능향상, 오라클교육, 오라클학원, SQL교육, SQL학원, 자바학원, 자바교육, SQL동영상

 오라클동영상,FORALL 기반 벌크 입력(BULK INSERT) 실습, DMLL성능향상, 오라클교육, 오라클학원, SQL교육, SQL학원, 자바학원, 자바교육, SQL동영상


http://ojc.asia/bbs/board.php?bo_table=LecSQLnPlSql&wr_id=722 


FORALL 기반 벌크 입력(BULK INSERT) 실습, DMLL성능향상, 오라클교육, 오라클학원, SQL교육, SQL학원, 자

FORALL 기반 벌크 입력(BULK INSERT) 실습, DMLL성능향상, 오라클교육, 오라클학원, SQL교육, SQL학원, 자바학원, 자바교육, SQL동영상오라클 PL/SQL성능향상을 위한FORALL기반 BULK INSERT실습[실습]사번(empno),

ojc.asia

https://www.youtube.com/watch?v=RE79vqW_s6o&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=31 


https://www.youtube.com/watch?v=mAQNkUZ_9CA&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=30 


https://www.youtube.com/watch?v=Ub3XCyENie0&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=25 

오라클 PL/SQL




성능향상을 위한

FORALL기반 BULK INSERT


실습




[실습]

사번(empno), 이름(ename), 직무(job) 3개의 컬럼을 갖는 BULKTEST라는 테이블을 생성하여 100만건 정도 데이터를 입력하는데. 개별 건씩 입력 하는것과 FORALL을 이용하여 벌크로 INSERT하는 방식의 성능차이에 대해 확인해 보겠습니다.

FORALL을 이용하여 DML문을 작성하면 한 번에 한 행씩 실행될 모든 DML 문을 생성하고 SQL 실행엔진에 한번에 모두 보냅니다.

FORALL 구문을 이용하면 INSERT, UPDATE, DELETE와 같은 DML 사용시 컬렉션을 사용하며 매우 빠르게 작업을 할 수 있습니다.

FORALL구문은 데이터를 오라클의 TABLE TYPE(배열)에 담아서 한번에 SQL 실행엔진에 넘겨서 실행을 하므로 성능 향상에 도움이 됩니다.


1. 실습 테이블 생성

create table bulktest (
empno number primary key,
ename varchar2(20),
job   varchar2(50));


set timing on
alter system flush SHARED_POOL;

2. 일반적인 반복문을 통한 개별 INSERT
-- 24초 경과
declare
          cnt number := 0;
begin
     while (cnt < 1000000) loop
            cnt := cnt + 1;
            insert /*+ loop insert */ into bulktest values ( cnt, cnt || '길동', '개발직');               
      end loop;
      commit;
end;



3. Shared Pool에서 파싱된 SQL문 및 실행횟수 확인

-- 오라클이 INSERT 구문을 내부적으로 바인드 변수 처리를 하여 SQL문장은 하나, 실행횟수는 1,000,000임을 알수 있습니다.
select substr(sql_text,1,60) "sql", count(*),
       sum(executions) "총실행횟수"
from v$sqlarea
where sql_text like '%loop%'
group by substr(sql_text,1,60)
having count(*) > 0
order by 2;

select count(1) from bulktest;
truncate table bulktest;

4. FORALL을 이용한 BULK INSERT

alter system flush SHARED_POOL;

-- 2초
declare
  type bulktype is table of bulktest%rowtype index by binary_integer;
  mydata bulktype;
begin
  for i in 1 .. 1000000 loop
    mydata(i).empno := i;
    mydata(i).ename := i || '길동';
    mydata(i).job := '개발직';
  end loop;

  forall i in 1 .. 1000000 insert /*+ bulk insert */  into bulktest values mydata(i);
  commit;
end;


5. Shared Pool에서 파싱된 SQL문 및 실행횟수 확인

-- 오라클이 INSERT 구문을 내부적으로 바인드 변수 처리를 하여 SQL문장은 하나, 실행횟수도 하나임을 확인할 수 있습니다.
select substr(sql_text,1,60) "sql", count(*),
       sum(executions) "총실행횟수"
from v$sqlarea
where sql_text like '%bulk%'
group by substr(sql_text,1,60)
having count(*) > 0
order by 2;


select count(1) from bulktest;
truncate table bulktest;



#FORALL, #벌크입력, #BULKINSERT, #SQL튜닝, #오라클교육, #오라클학원,#SQL교육, #SQL학원, #자바학원, #자바교육, #SQL동영상, FORALL, 벌크입력, BULKINSERT, SQL튜닝, 오라클교육, 오라클학원,SQL교육, SQL학원, 자바학원, 자바교육, SQL동영상


2021년 12월 23일 목요일

오라클 옵티마이저 모드, 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교육, 오라클교육, 
 



2021년 12월 10일 금요일

오라클 SQL교육, Distinct를 Exists로, Distinct란?, SQL TIP, 오라클학원/자바학원/SQL학원교육/오라클교육

 

오라클 SQL교육, Distinct를 Exists로, Distinct란?, SQL TIP, 오라클학원/자바학원/SQL학원교육/오라클교육


http://ojc.asia/bbs/board.php?bo_table=LecOrccleTun&wr_id=160 


오라클 SQL교육, Distinct를 Exists로, Distinct란?, SQL TIP

오라클 SQL교육, Distinct를 Exists로, Distinct란?, SQL TIPSQL TIPdistinct?distinct를 exists로실습 : 오라클19CDISTINCT는 SELECT List에서 레코드의 중복을 제거하기 위해서 사용합니다. DISTINCT 키워드 뒤에는 둘 이상

ojc.asia



https://youtu.be/BVeBkyIWUrU


SQL TIP





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

distinct?

distinct를 exists로


실습 : 오라클19C



DISTINCT는 SELECT List에서 레코드의 중복을 제거하기 위해서 사용합니다. DISTINCT 키워드 뒤에는 둘 이상의 컬럼을 지정할 수 있는데 선택한 모든 열을 기준으로 중복을 제거하여 고유한 값 조합을 표시 합니다.




SELECT DISTINCT expressions  
FROM 테이블 
WHERE 조건절;  


COUNT(DISTINCT 컬럼) 형식에서는 하나의 컬럼만 사용가능 합니다.


– 여러 컬럼을 사용하려면  CONCAT을 이용하여 우회 합니다.
SELECT  COUNT(   DISTINCT  CONCAT  (  EMPNO,   ENAME  ) ) A
FROM  EMP;


이러한 distinct는 중복을 제거하기 위해 내부적으로 정렬(SORT)를 동반하므로 대용량의 테이블에서는 사용에 조심해야 합니다.


실습


-- 실습을 위한 테이블의 데이터를 확인 합니다.
-- 사원
SELECT * FROM MYEMP1;

-- 수강
SELECT * FROM MYSUGANG1;

-- 한 사원이 여러강좌를 수강할 수 있으므로 count(empno) 건수가 훨씬 많습니다.
SELECT COUNT(EMPNO) FROM MYSUGANG1;
SELECT COUNT(DISTINCT EMPNO) FROM MYSUGANG1;

-- 테이블에 생성 되어 있는 인덱스를 확인 합니다.
SELECT TABLE_NAME, INDEX_NAME 
FROM USER_INDEXES 
WHERE TABLE_NAME = 'MYSUGANG1';

SELECT * FROM USER_IND_COLUMNS
WHERE INDEX_NAME = 'PK_SUGANG';

-- 한과목 이상 수강한 사원이름 추출, 
-- 수강 테이블에 사원은 여러 과목을 들을 수 있어서 여러건 있음
SELECT DISTINCT E.ENAME
FROM   MYEMP1 E  INNER JOIN MYSUGANG1 S
ON  E.EMPNO = S.EMPNO;

-- EXISTS를 사용하여 변환 합니다.
SELECT E.ENAME
FROM    MYEMP1 E
WHERE  EXISTS ( SELECT 1 FROM MYSUGANG1 S
                WHERE E.EMPNO = S.EMPNO);              





#SQL튜닝, #오라클튜닝, #distinct, #오라클교육, #SQL교육, #오라클학원, #SQL학원, #SQL동영상, #오라클동영상,

SQL튜닝, 오라클튜닝, distinct, 오라클교육, SQL교육, 오라클학원, SQL학원, SQL동영상, 오라클동영상

(자바오라클잘하세요)오라클 SQL튜닝, WHERE절에서 SQL함수 사용튜닝, 함수기반인덱스, 자바학원, 오라클학원

 

(자바오라클잘하세요)오라클 SQL튜닝, WHERE절에서 SQL함수 사용튜닝, 함수기반인덱스, 자바학원, 오라클학원


http://ojc.asia/bbs/board.php?bo_table=LecOrccleTun&wr_id=159 


오라클 SQL튜닝, WHERE절에서 SQL함수 사용튜닝, 함수기반인덱스

오라클 SQL튜닝, WHERE절에서 SQL함수 사용튜닝, 함수기반인덱스SQL TIPWHERE절에서 SQL함수의 사용실습 : 오라클19CWHERE절의 컬럼에 SQL함수를 사용하는 것은 부담스러운 일 입니다. 특히 인덱스가 걸려

ojc.asia



https://youtu.be/RsswtJnUFP0

https://www.youtube.com/watch?v=F81s1_q4Fqo&list=PLxU-iZCqT52DFRbLFQIgGUFp-5En2DYRG&index=15&t=2s 

SQL TIP



WHERE절에서 SQL함수의 사용



실습 : 오라클19C



WHERE절의 컬럼에 SQL함수를 사용하는 것은 부담스러운 일 입니다. 특히 인덱스가 걸려 있는 컬럼인데 SQL 함수가 사용되었다면 그 인덱스는 사용할  수가 없어 원본 데이터인 전체 테이블 FULL SCAN을 하므로 성능이 저하 됩니다.


WHERE절에서는 좌측 컬럼에 대해서는 함수 사용을 피하고 오른쪽 (문자)상수쪽에 SQL함수를 사용해야 인덱스를 사용하는데 문제가 없으며, 부득이 사용해야 한다면 함수기반 인덱스를 사용해야 합니다.


다음과 같은 예를 보겠습니다.



-- MYEMP1 테이블은 2000만건 정도 있는 테이블 입니다.
SELECT COUNT(*) FROM MYEMP1;
SELECT * FROM MYEMP1;

-- MYEMP1 테이블에 생성되어 있는 인덱스를 확인 합니다.
SELECT TABLE_NAME, INDEX_NAME 
FROM USER_INDEXES 
WHERE TABLE_NAME = 'MYEMP1';

-- ename 컬럼은 인덱스가 생성되어 있어서 빨리 조회됩니다.
SELECT * FROM MYEMP1
WHERE ENAME = '가길동281';

-- like인 경우도 인덱스 컬럼인 ename에 변현이 안되었으므로
-- 인덱스를 경유하여 빨리 조회 됩니다.
SELECT COUNT(*) FROM MYEMP1
WHERE ENAME LIKE '다길동%';

-- 인덱스 컬럼인 ename에 변형이 생겨 인덱스를 이용할수 없습니다.
-- 시간이 더 걸립니다.
SELECT COUNT(*) FROM MYEMP1
WHERE SUBSTR(ENAME, 0, 3) = '다길동';

-- 꼭 WHERE절의 컬럼에 대해 SQL함수를 사용해야 한다면 
-- 함수기반 인덱스를 만드세요.
DROP INDEX FIDX_MYEMP1_ENAME;
CREATE INDEX FIDX_MYEMP1_ENAME ON MYEMP1( SUBSTR(ENAME, 0, 3) );

-- 함수가반 인덱스를 생성 후 실행하니 빨리 조회 됩니다.
SELECT COUNT(*) FROM MYEMP1
WHERE SUBSTR(ENAME, 0, 3) = '다길동';




#SQL튜닝, #오라클튜닝, #함수기반인덱스, #오라클교육, #SQL교육, #오라클학원, #SQL학원, #SQL동영상, #오라클동영상,

SQL튜닝, 오라클튜닝, 함수기반인덱스,오라클교육, SQL교육, 오라클학원, SQL학원, SQL동영상, 오라클동영상


(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...