인덱스 사용
인덱스와 B-tree
만능형: B-tree
- 데이터를 트리 구조로 저장하는 형태
- 대부분의 데이터베이스에서는 트리의 리프 노드에만 키값을 저장하는 B+tree 사용
- 루트와 리프의 거리를 가능한 일정하게 유지하므로 검색 성능이 안정적
기타 인덱스
- 비트맵 인덱스
- 데이터를 비트 플래그로 변환
- 카디널리티가 낮은 필드에 유효
- 갱신할 때 오버헤드가 크므로 BI/DWH 용도로 사용
- 해시 인덱스
- 카디널리티: 값의 균형을 나타냄
- 카디널리티가 높은 필드는 모든 레코드에 다른 값이 들어가 있는 유일 키 필드
- 카디널리티가 낮은 필드는 모든 레코드에 같은 값이 들어가 있는 필드
- 선택률: 특정 필드 값을 지정했을 때 테이블 전체에서 몇 개의 레코드가 선택되는지를 나타냄
인덱스를 사용하는 것이 좋은지 판단하려면
- 인덱스를 작성하는 필드 집합의 조건
- 레코드를 압축하는
WHERE
구가 없으므로 인덱스로 작성할 필드도 존재하지 않음레코드를 제대로 압축하지 못하는 경우
SELECT order_id, receive_date FROM Orders WHERE process_flg = '5'
process_flg = 5
인 레코드의 선택률이 높을 경우 레코드 갯수가 거의 줄어들지 않으므로 테이블 풀 스캔보다 더 느려질 수도 있음인덱스가 제대로 작동하려면 레코드를 크게 압축할 수 있어야 함
- 입력 매개변수에 따라 선택률이 변동하는 경우 - 1
SELECT order_id FROM orders WHERE receive_date BETWEEN :start_date AND :end_date
- 조건이 매개변수화 되어 있을 경우 입력에 따라 선택률이 높아지거나 낮아짐
- 입력 매개변수에 따라 선택률이 변동하는 경우 - 2
SELECT COUNT(*) FROM orders WHERE shop_id = :sid
- 중간 일치, 후방 일치의 LIKE 연산자
SELECT order_id FROM Orders WHERE shop_name LIKE '%대공원%'
LIKE
연산자를 사용하는 경우 인덱스는 전방 일치(대공원%
)에만 적용 가능
- 색인 필드로 연산하는 경우
SELECT * FROM SomeTable WHERE col_1 * 1.1 > 100
- 색인 필드로 연산하는 경우에는 인덱스를 사용할 수 없음
- 검색 조건의 우변에 식을 사용하도록 수정하면 인덱스를 사용할 수 있음 (
WHERE col_1 > 100 / 1.1
) - 마찬가지로, 색인 필드에 함수를 사용하는 경우에도 인덱스를 사용할 수 없음
- IS NULL을 사용하는 경우
- 일반적으로 색인 필드의 데이터에
NULL
이 존재하지 않기 때문에 인덱스를 사용할 수 없음
- 일반적으로 색인 필드의 데이터에
- 부정형을 사용하는 경우
- UI 설계로 처리
- 시스템을 전체적으로 조감해주는 사람이 없다면 성능을 최적화하기 어려움
- 테스트 단계에서 성능 문제가 발견될 경우 외부 설정 변경은 사용할 수 없음
데이터 마트로 대처
- 데이터 마트란 특정한 쿼리(군)에서 필요한 데이터만을 저장하는 상대적으로 작은 크기의 테이블
CREATE TABLE OrderMart (order_id CHAR(4) NOT NULL, receive_date DATE NOT NULL)
데이터 마트를 채택할 시 주의점
- 데이터 신선도
- 동기 사이클이 짧으면 성능 이슈 발생, 길면 신선도가 낮아짐
- 데이터 마트 크기
- 테이블의 크기를 줄일 수 없으면 데이터 마트를 만들어도 성능 이득을 얻을 수 없음
- GROUP BY 절을 사용하여 집계를 마치면 효과적
- 데이터 마트 수
- 데이터 마트는 ER에 등장하지 않으므로 제대로 관리하기 어려움
- 사용하지 않는 데이터 마트의 수를 줄이기 위해 데이터 마트에 지나치게 의존하면 안됨
- 배치 윈도우
- 특정한 필드를 커버할 수 있는 커버링 인덱스(Covering Index)를 작성
CREATE INDEX CoveringIndex ON Orders (order_id, receive_date)
- 이러한 인덱스를 작성하면 다음과 같은
SELECT
문에서 테이블 풀 스캔이 아닌 인덱스 온리 스캔을 사용SELECT order_id, receive_date FROM Orders
- 데이터 마트를 사용할 때와 마찬가지로 I/O 비용 절감
- 테이블 필드의 부분 집합만 저장하므로 원래 테이블에 비해 크기가 작음
- 애플리케이션 수정이 불필요
- 로우(레코드) 지향 저장소의 DBMS에 유사적으로 컬럼(필드) 기반 저장소를 실현
인덱스 온리 스캔의 주의점
- DBMS가 지원해야 사용할 수 있음
- 한 개의 인덱스에 포함할 수 있는 필드 수에 제한이 있음
- 갱신 오버헤드 증가
- 정기적인 인덱스 리빌드 필요
- SQL 구문에 새로운 필드가 추가된다면 사용할 수 없음