* Youtube Link - https://www.youtube.com/watch?v=98y70kDWxwM&list=PLVsNizTWUw7FzFgU1qe-n7_M7eMFA9d-f&index=26
인덱스의 성능 비교
대용량 데이터를 이용한 성능비교를 해보려고 한다.
INDEX를 생성하지 않은 Emp 테이블
INDEX를 생성한 Emp_idx 테이블을 만들어서
성능 비교를 해보겠다.
전체 총 데이터는 300024건이다.
ORDER BY DBMS_RANDOM.VALUE를 통해서
랜덤으로 ORDER BY를 하였다.
SELECT DBMS_RANDOM.VALUE FROM dual
UNION ALL
SELECT DBMS_RANDOM.VALUE FROM dual
UNION ALL
SELECT DBMS_RANDOM.VALUE FROM dual;
를 해보면 다음과 같이 소수점으로 데이터가 임의의 값으로 출력되는 것을 볼 수 있다.
그리고 이렇게 출력을 해보면 조회가 잘 되는 것을 볼 수 있다.
USER_INDEXES 테이블에서 조회를 해보면
EMP 테이블과 EMP_INDEX 테이블에 INDEX 생성이 안 된 것을 볼 수 있다.
이번에는 EMP 테이블에 empNo에 INDEX를 생성하였다.
그리고 USER_INDEXES 테이블에서 확인을 해보면
EMP_INDEX 테이블에 INDEX가 생성된 것을 볼 수 있다.
리프 블록은 총 669개가 만들어진 것을 볼 수 있다.
DISTINCT_KEYS 를 통해서 각 PK가 다른 것을 볼 수 있다.
NUM_ROWS 를 통해서 약 30만건의 데이터에 INDEX를 생성한 것을 볼 수 있다.
그러면 이렇게 데이터 블록 위헤
인덱스 블록 (루트 블록, 중간 블록, 리프 블록)이 생성되는 것을 볼 수 있다.
인덱스 블록은 실제 데이터 블록의 주소를 참조한다.
- 버퍼 비우기
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH SHARED_POOL;
이 두 명령어를 통해서 버퍼를 계속 비우고 다음 쿼리들을 실행해보겠다.
- 자동추적
아이콘들 중 자동 추적을 클릭한다.
physical reads | 1827 |
인덱스가 없는 테이블을 자동추적을 해보았다.
physical reads가 1827건이다.
30만건의 데이터 중 1827건의 데이터를 조회해서 결과를 불러왔다.
physical reads | 325 |
이번에는 인덱스가 있는 테이블을 조회를 해서 자동추적을 해보았다.
physical reads 를 보면 325건의 데이터만 조회가 되었다.
굉장히 빠르게 조회가 되는 것을 볼 수 있다.
숫자에 연연하기 보다도 인덱스가 있는 테이블이 physical reads가 훨씬 더 적다. 이 부분에 의미를 두면 될 것 같다.
- 범위 자동추적
physical reads | 1039 |
인덱스가 없는 테이블에 범위 검색을 해보았다.
자동 추적을 해보니 physical reads가 1039건이다.
physical reads | 366 |
인덱스가 있는 테이블에 범위 검색을 해보았다.
자동 추적을 해보니 physical reads가 366건이다.
훨씬 적은 것을 볼 수 있다.
물론 이 physical reads는 매번 건수가 다르다.
인덱스가 없으면 TABLE FULL SCAN을 하면 데이터 블록에서 일일이 전체를 찾아야 한다.
하지만 인덱스를 만들면 인덱스 블록에서 찾아서 데이터 블록과 왔다 갔다 하면서 데이터를 찾는다.
- 힌트
physical reads | 423 |
SELECT /*+ FULL(Emp_idx) */
* FROM Emp_idx WHERE emp_no < 11000; -- 약 999건을 조회함
이렇게 힌트를 주면
TABLE FULL SCAN을 할 수 있다.
옵티마이저가 인덱스 블록에서 데이터 블록까지 왔다 갔다 해야할 수가 많으면
자동으로 TABLE FULL SCAN을 한다.
physical reads | 366 |
physical reads가 366건이 나왔다.
힌트를 통해서 인덱스를 사용하도록 해보았다.
때로는 힌트를 사용하는 것 보다 옵티마이저가 실행하는 것이 더 옳을 수 있다.
SELECT /*+ INDEX(Emp_idx IDX_EMPIDX_EMONO) */
* FROM Emp_idx WHERE emp_no < 11000;
옵티마이저가 자동으로 하기 때문에
가끔 INDEX를 사용해야 하는데 안 사용하고, INDEX를 사용하면 안 되는데 사용하는 경우가 많다.
그러한 경우 힌트를 사용하면 좋다.
- 주의점(1): 인덱스 컬럼에 연산을 가하지 마라, 인덱스를 사용하지 못하고 TABLE FULL SCAN을 한다.
INDEX 열에 어떠한 연산을 가하면
인덱스를 사용하지 않는다.
다음과 같이 TABLE FULL SCAN을 한 것을 볼 수 있다.
physical reads | 325 |
SELECT * FROM Emp_idx WHERE emp_no = 20000/1;
이러한 경우 이렇게 컬럼이 아닌 비교할 데이터에 연산을 가하면 피할 수 있다.
다음과 같이 인덱스를 정상적으로 실행한 것을 볼 수 있다.
- 주의점(2): 중복도가 높다, 선택도가 낮다면 인덱스를 사용하는 것이 보통 훨씬 더 나쁜 결과를 낳는다.
개수는 30만건인데, 키의 개수는 2건밖에 없다.
이러한 경우는 의미가 없는 인덱스이다.
인덱스를 사용을 하면 지금은 빠르지만
일반적으로 훨씬 나쁜 결과를 낳는다.
또는 있거나 없거나다. 정렬할 필요가 없기 때문이다.
인덱스 블럭에서 데이터 블럭까지 왔다 갔다하는 횟수가 많기 때문이다.
작동개념을 알고 있어야 인덱스를 생성해야 하는 경우와 그렇지 않은 경우를 알 수 있다.
인덱스의 효과
인덱스는 열 단위에 생성된다.
WHERE절에서 사용되는 열에 인덱스를 만들어야 한다.
WHERE절이어도 자주 사용되어야 한다.
데이터의 중복도가 높은, 선택도가 낮은 열은 인덱스를 만들어도 별 효과가 없다.
JOIN을 하는 열에 인덱스를 생성시켜주는 것이 좋다.
INSERT/UPDATE/DELETE가 많은 테이블은 인덱스를 최소화해주는 것이 좋다.
사용하지 않는 인덱스는 제거해주는 것이 좋다.
인덱스는 주기적으로 재구성해서 조각화를 최소화하는 것이 시스템의 성능을 최상으로 유지하는 방법이다.
인덱스는 자동정렬한다.
- 인덱스 재구성
다음과 같이
ALTER INDEX idx_Emp_gender REBUILD; 명령어를 통해서
ALTER문으로 INDEX를 REBUILD(재구성)할 수 있다.
주기적으로 하면 시스템 성능에 도움이 된다.
인덱스는 계속 조각화되기 때문이다.
감사합니다.
'Oracle' 카테고리의 다른 글
[이것이 오라클이다] 10장 2교시: [Oracle] 저장 프로시저 실습, 저장 프로시저 특징 (6) | 2024.11.08 |
---|---|
[이것이 오라클이다] 10장 1교시: [Oracle] 저장 프로시저 개념과 형식, 파라미터, PL/SQL 변수 (4) | 2024.11.08 |
[이것이 오라클이다] 09장 3교시: [Oracle] 인덱스의 생성/변경/삭제 (1) | 2024.11.07 |
[이것이 오라클이다] 09장 2교시: [Oracle] 인덱스의 내부 작동 (2) | 2024.11.07 |
[이것이 오라클이다] 09장 1교시: [Oracle] 인덱스 개념, 종류, 자동생성 (2) | 2024.11.07 |