DB/SQL

[Oracle] I/O

호두밥 2022. 4. 5. 19:20

인덱스란? 

인덱스란, 데이터를 찾기 위한 "목차"입니다. 인덱스 구성 칼럼의 순서에 따라 정렬된 데이터를 가지고 있습니다.

인덱스가 생성되는 경우

  • 기본 키인 경우 기본키 구성 칼럼의 순서에 따라 인덱스가 생성됩니다.
  • 추가로 unique/ununique 인덱스를 생성해줄 수 있습니다. 

 

인덱스를 사용하면 좋은 이유

  • 소량의 데이터를 찾을 때 빠릅니다.
  • 인덱스를 이용해 데이터를 찾으면 인덱스 칼럼 순서에 따라 이미 정렬된 데이터를 조회할 수 있습니다. (정렬 부하 ↓)

인덱스가 빠른 이유

https://ko.wikipedia.org/wiki/이진_검색_알고리즘

인덱스는 정렬된, 이진트리 자료구조로 저장됩니다. 때문에 데이터를 탐색할 때 이진탐색 방법을 사용하게 됩니다.

1~100 중에 10을 찾아야 된다고  가정합니다. 그러면, 1~100을 절반으로 나눕니다. 그리고 10이 포함되어 있는 영역인 1~50으로 이동합니다. 또 절반을 나누어 1~25로 이동합니다. 이런 방식으로 남은 범위를 절반씩 나누어 이동하다보면 8번이면 10을 찾아낼 수 있습니다.

즉 100개에서 1개의 데이터를 찾기 위해서는 7 < log₂100 < 8 번만 탐색하면 됩니다.  

블록 IO

블록은 디스크에 저장된 데이터를 메모리로 꺼내오는, 최소 운반 단위입니다. 

데이터를 처리하기 위해서는 찾으려는 데이터가 저장된 블록 1개를 모두 읽어서 메모리로 가져와야 합니다. 그렇기 때문에 같은 데이터 블록에 접근하는 아래 두 쿼리의 cpu_cost가 8341 byte로 동일합니다. 

다만 고객에게 보여주는 데이터의 양에는 차이가 있습니다. 첫 번째는 item_nm 칼럼만 조회하기 때문에 24byte를, 두번째 쿼리는 테이블 칼럼 전체(*)를 조회하기 때문에 84byte를 보여줍니다.    

얼마만큼의 데이터 블록을 메모리로 가져올지, 그 블록의 양과 접근 횟수를 최대한 줄일 수 있도록 블록 IO를 효율화 해야 합니다. 

select item_nm from item where ITEM_ID = 1;

select * from item where ITEM_ID = 1;

 

시퀀셜 액세스와 랜덤 액세스

인덱스를 통한 데이터 탐색 절차

  1. 인덱스 루트 블록부터 리프 블록까지 스캔 (랜덤 액세스 방식)
  2. 리프 블록에서 조건을 만족하는 구간까지 스캔(시퀀셜 액세스 방식)
  3. 리프 블록과 연결된 원본 데이터 테이블을 스캔 (랜덤 액세스 방식) 

 

 

인덱스 탐색에서 주의할 점

  • 수평적 탐색 시 필요한 구간만 탐색하도록 하여 랜덤 액세스를 줄여야 합니다.
  • 인덱스를 효율적으로 구성해, 수평적 탐색결과 = 접근할 원본 데이터와 거의 동일하도록 해야 합니다.

 

블록 IO 효율화를 위한 기능

 

버퍼피닝 Buffer pinning

랜덤 액세스 과정에서 (원본 데이터 테이블 탐색) 연속적으로 같은 블록에 접근하는 경우, 랜덤 액세스를 생략하는 것을 말합니다. (일종의 캐시기능)

클러스터링 팩터가 좋다면 (원본 테이블의 데이터가 인덱스와 동일한 순서로 저장되어 있다면) 랜덤 액세스 과정이 적게 일어날 수 있습니다. 

 

싱글 블록 IO, 멀티블록 IO

싱글 블록 IO는 한번에 데이터 블록 1개씩만 읽어오는 방식입니다. 인덱스를 이용한 탐색을 하는 경우 싱글 블록 IO 방식을 사용하게 됩니다. 

멀티 블록 IO는 한번에 앞뒤로 인접한 데이터 블록 여러 개를 함께 읽어오는 방식입니다. 테이블 풀 스캔이 일어나는 경우 멀티 블록 IO 방식을 사용하게 됩니다. 

멀티블록 IO의 크기

  • 익스텐트가 가지는 블록 갯수
  • db_file_multiblock_read_count 파라미터

두 요소 중 작은 값의 크기로 블록을 가져옵니다. (블록의 크기 Default 8kb)