2025-09-08
오늘 배운 것
8.3.3 B-Tree 인덱스 사용에 영향을 미치는 요소
- 칼럼의 크기, 레코드 건수, 유니크한 인덱스 키 값의 개수
8.3.3.1 인덱스 키 값의 크기
- 페이지 OR 블록 : 디스크에 데이터를 저장하는 가장 기본 단위
- 디스크의 모든 읽기 및 쓰기 작업의 최소 작업 단위
- 버퍼 풀에서 데이터를 버퍼링하는 기본 단위
- B-Tree 자식 노드의 개수는 가변적
- 인덱스의 페이지 크기와 키 값의 크기에 따라 결정
- 키 값이 커지면 한 페이지에 저장되는 키의 개수가 줄어듬
- 즉, 인덱스를 구성하는 키 값의 크기가 커지면 디스크로부터 읽어야 하는 횟수가 늘어나고, 그만큼 느려짐
- 키값의 길이가 길어진다 → 전체 적인 인덱스의 크기가 커짐
- 하나의 레코드를 위한 인덱스 크기가 커지면 커질수록 메모리에 캐시해 둘 수 있는 레코드 수 감소 → 메모리 효율이 떨어짐
8.3.3.2 B-Tree 깊이
- B-Tree의 깊이는 MySQL에서 값을 검색할 때 몇 번이나 랜덤하게 디스크를 읽어야 하는지와 직결
- 인덱스 키 값의 크기가 커지면 커질수록 하나의 인덱스 페이지가 담을 수 있는 인덱스 키 값의 개수 감소
- 이에 따라 B-Tree의 깊이가 깊어져서 디스크 읽기가 더 많이 필요
- 따라서 인덱스 키 값의 크기는 가능하면 작게 만드는 것이 좋음
8.3.3.3. 선택도(기수성)
- 선택도 OR 기수성 : 모든 인덱스 키 값 가운데 유니크한 값의 수
- 인덱스는 선택도가 높을수록 검색 대상이 줄어들기 때문에 빠르게 처리가능
8.3.3.4 읽어야 하는 레코드의 건수
- 인덱스를 통해 테이블의 레코드 읽기 > 바로 테이블의 레코드 읽기
- 인덱스를 통해 읽어야 할 레코드의 건수가 전체 테이블의 20% ~ 25%를 넘어서면 인덱스를 이용하지 않고 테이블을 모두 직접 읽어서 필요한 레코드만 가려내는(필터링) 방식으로 처리하는 것이 효율적
8.3.4 B-Tree 인덱스를 통한 데이터 읽기
8.3.4.1 인덱스 레인지 스캔
- 가장 빠른 방법
- 검색해야 할 인덱스의 범위가 결정됐을 때 사용하는 방식
- 방법
- 인덱스 탐색 : 루트 노드에서부터 비교를 시작해 브랜치 노드를 거치고 최종적으로 리프노드까지 찾아 들어가 레코드의 시작 지점 찾기
- 인덱스 스캔 : 시작해야할 위치부터 리프노드의 레코드를 순서대로 읽음
- 리프 노드의 끝까지 읽으면 리프 노드 간의 링크를 이용해 다음 리프노드를 찾아서 다시 스캔
- 스캔을 멈춰야할 위치에 도달 시, 지금까지 읽은 레코드를 반환하고 쿼리 마침
- 인덱스로 읽은 것수가 전체 테이블의 20~25% 이상일 때 왜 안쓰는게 더 효율적인가?
- 리프노드를 스캔하면서 실제 데이터 파일의 레코드를 읽어와야 하는 경우
- 리프 노드들은 인덱스 자체의 정렬 특성 때문에 정렬된 상태로 레코드를 가져옴
- 하지만 실제 데이터 파일에 레코드들을 이렇게 정렬되어 있지 않음
- 만약 인덱스의 키값 외의 추가 컬럼 값이 필요하면 해당 레코드 한건한건 랜덤 I/O 로 읽어와야함
- 따라서 20 ~25%이상이면 그냥 필터링 하는것이 더 효율적
- 커버링 인덱스 : 인덱스로 처리가 완료되는 쿼리라 디스크의 레코드를 읽지 않아도 되는 것
8.3.4.2 인덱스 풀 스캔
- 인덱스의 처음부터 끝까지 모두 읽는 방식
- 쿼리의 조건절에 사용된 칼럼이 인덱스의 첫 번째 칼럼이 아닌 경우에 사용
- 인덱스의 크기는 테이블의 크기보다 작으므로 인덱스만 읽는것이 테이블을 처음부터 끝까지 읽는 것보다 효율적
- 따라서 쿼리가 인덱스에 명시된 칼럼만으로 조건 처리가 가능할 때 인덱스 풀 스캔 사용
- 방법
- 인덱스 리프노드의 제일 앞 또는 제일 뒤로 이동
- 인덱스의 리프노드를 연결하는 연결리스트를 따라서 처음부터 끝까지 스캔
8.3.4.3 루스 인덱스 스캔
- 타이트 인덱스 스캔 : 인덱스 레인지 스캔, 인덱스 풀 스캔
- 인덱스 레인지 스캔과 비슷하게 작동하지만 중간에 필요하지 않은 인덱스 키값은 무시하고 다음으로 넘어감
- GROUP BY 또는 MAX(), MIN()함수에 대해 최적화 하는 경우 사용
8.3.4.4 인덱스 스킵 스캔
- 8.0 이전 버전 까지는 복합인덱스의 한 컬럼이라도 비교 조건을 안하면 해당 인덱스를 사용할 수 없었음
- 이러한 문제를 해결한 것이 인덱스 스킵 스캔
- 루스 인덱스 스캔과의 차이점
- 루스 인덱스 스캔은 GROUP BY 작업을 처리하기 위한 사용
- 방법
- 복합 인덱스에서 비교하지 않은 컬럼의 유니크한 값을 모두 조회해 주어진 쿼리에다가 해당 유니크 한 값들의 조합들을 전부 쿼리하는 방식
- 단점
- 조건이 없는 인덱스의 선행 칼럼이 유니크한 값의 개수가 적어야함
- 개수가 많으면 오히려 인덱스를 사용하는 것이 느려질 수 있음
- 쿼리가 인덱스에 존재하는 칼럼만으로 처리가 가능해야 함 (커버링 인덱스)
8.3.5 다중 칼럼(Multi-column) 인덱스
- 두 개 이상의 칼럼으로 구선된 인덱스
- 두 번째 칼럼은 첫 번째 칼럼에 의존해서 정렬되어 있음
- 따라서 인덱스 내에서 각 칼럼의 위치가 상당히 중요
8.3.6 B-Tree 인덱스의 정렬 및 스캔 방향
- 인덱스 키 값은 항상 오름차순이거나 내림차순으로 정렬되어 저장
- 오름차순으로 정렬되어 있다 하더라도 그 인덱스를 거꾸로 읽으면 내림차순과 같음
8.3.6.1 인덱스의 정렬
8.3.6.1.1 인덱스 스캔 방향
- 인덱스 생성 시점에 오름차순 또는 내림차순으로 정렬 결정
- 쿼리가 그 인덱스를 사용하는 시점에 인덱스를 읽는 방향에 따라 오름차순 또는 내림 차순 정렬 효과 적용
8.3.6.1.2 내림차순 인덱스
- 인덱스 역순 스캔이 인덱스 정순 스캔에 비해 느린 이유
- 페이지 잠금이 인덱스 정순 스캔에 적합한 구조
- 페이지 내에서 인덱스 레코드가 단방향으로만 연결된 구조
- 내림차순 조회가 많다면 오름 차순 인덱스를 역순으로 읽는 것보단 내림차순 인덱스를 정의하는 것이 더 좋음
- 인덱스의 앞쪽만 또는 뒤쪽만 집중적으로 읽어서 인덱스의 특정 페이지 잠금이 병목이 될 것으로 예상된다면, 쿼리에서 자주 사용되는 정렬 순서대로 인덱스를 생성하는 것이 잠금 병목 현상을 완화하는 데 도움이 될 것임
8.3.7 B-Tree 인덱스의 가용성과 효율성
8.3.7.1 비교조건의 종류와 효율성
- 필터링 : 인덱스를 통해 읽은 레코드가 나머지 조건에 맞는지 비교하면서 취사 선택하는 작업
- 작업 범위 결정 조건 : 작업의 범위를 결정하는 조건
- 필터링 조건 OR 체크 조건 : 비교 작업의 범위를 줄이지 못하고 단순히 거름 종이 역할만 하는 조건
- 작업 범위 결정 조건이 많을수록 쿼리 성능 증가
- 체크 조건은 오히려 느리게 만드는 경우가 많음
8.3.7.2 인덱스의 가용성
- 왼쪽 값을 기준으로 정렬되어 있기 때문에 인덱스의 설정 순서를 잘 못두면 인덱스가 작업 범위 결정 조건이 되지 못해 인덱스의 가용성을 떨어뜨린다.
8.3.7.3 가용성과 효율성 판단
- B-Tree 인덱스의 작업 범위 결정 조건으로 사용 할 수 없는 조건
- NOT-EQUAL로 비교된 경우(<>, NOT IN, NOT BETWEEN, IS NOT NULL)
- LIKE %??(앞부분이 아닌 뒷부분 일치) 형태로 문자열 패턴이 비교된 경우
- 스토어드 함수나 다른 연산자로 인덱스 칼럼이 변형된 후 비교된 경우
- NOT-DETERMINISTIC 속성의 스토어드 함수가 비교 조건에 사용된 경우
- 데이터 타입이 서로 다른 비교(인덱스 칼럼의 타입을 변환해야 비교가 가능한 경우)
- 문자열 데이터 타입의 콜레이션이 다른 경우
- 다중 칼럼 인덱스
- 작업 범위 결정 조건으로 인덱스를 사용하지 못하는 경우
- 첫번째 컬럼에 대한 조건이 없을 때
- 처번째 컬럼의 비교조건이 B-Tree 인덱스의 작업 범위 결정 조건으로 사용 할 수 없는 조건인 경우
- 작업 범위 결정 조건으로 인덱스를 사용하는 경우
- 선행 컬럼들까지 동등 비교형태로 비교할 때
- 특정 컬럼에 대해 아래 조건으로 비교할 때
- 동등비교
- 크다 작다
- LIKE로 좌측 일치 패턴
8.4 R-Tree 인덱스
- R-Tree(공간 인덱스) : 2차원의 데이터를 인덱싱하고 검색하는 목적의 인덱스
- MySQL의 공간 확장
- 공간 데이터를 저장할 수 있는 데이터 타입
- 공간 데이터의 검색을 위한 공간 인덱스(R-Tree 알고리즘)
- 공간 데이터의 연산 함수(거리 또는 포함관계의 처리)
8.4.1 구조 및 특성
- 데이터 타입
- Point
- LINE
- POLYGON
- GEOMETRY : 나머지 3개의 슈퍼 타입으로 위 3개의 객체를 모두 저장 가능
- MBR(Minimum Bounding Rectangle) : 해당 도형을 감싸는 최소 크기의 사각형
- R-Tree : MBR들의 포함관계를 B-Tree 형태로 구현한 인덱스
- 최하위 MBR → 리프 노드
- 최상위 MBR → 루트 노드
- 그외 MBR → 브랜치 노드
8.4.2 R-Tree 인덱스의 용도
- WGS84(GPS)기준의 위도, 경도 좌표 저장
- 좌표 시스템에 기반을 둔 정보 저장
- 함수
- ST_Contains(사각 상자, px)
- ST_Within(px, 사각상자)
- 위 함수를 활용해서 특정 거리 이내의 사각형들을 조회하고 ST_Distance_Sphere()함수로 필터링 하면 특정 거리 내의 위치들을 조회할 수 있음