인덱스 기본동작
인덱스는 정렬된 자료구조로서 이를 통해 탐색범위를 최소화 한다.
데이터주소 | name | age |
---|---|---|
1 | 홍길동 | 23 |
2 | 이훈재 | 35 |
3 | 임꺽정 | 33 |
4 | 이순신 | 32 |
이 테이블에 age를 인덱스로 잡으면
age | 데이터주소 |
---|---|
23 | 1 |
32 | 4 |
33 | 3 |
35 | 2 |
인덱스를 걸어둔 컬럼(age)을 기준으로 정렬한 테이블이 하나 생긴다.
쿼리가 들어오면 인덱스를 먼저 확인한다.
인덱스를 이용한 검색자료구조
- HashMap
- 단건 검색속도 O(1)
- 범위 검색 속도 O(N)
- 전방 일치 탐색 불가
- ex) like 'AB%'
- List
- 정렬되지 않은 리스트 O(N)
- 정렬된 리스트 O(logN)
- 정렬되지 않은 리스트의 정렬 시간 복잡도 O(N) ~ O(N * logN)
- 삽입/ 삭제 비용 매우 높음
- Tree
- 트리 높이에 따라 시간 복잡도가 결정됨
- 트리의 높이를 최소화 하는것이 중요
- 한쪽의 노드가 치우치지 않도록 균형을 잡아누는 트리 사용
- B + Tree
- 삽입 / 삭제시 항상 균형을 이훔
- 하나의 노드가 여러 개의 자식 노드를 가질수 있음
- 리프노트에만 데이터 존재
- 연속적인 데이터 접근시 유리
- 대부분의 RBDMS는 B+Tree사용
데이터가 추가되거나 수정될때 B+Tree모양이 바뀌기 때문에
조회성능은 높아질수있겠지만 추가, 수정은성능이 낮아진다.
클러스터 인덱스
- 클러스터 인덱스는 데이터 위치를 결정하는 키 값이다.
- MySQL의 PK는 클러스터 인덱스다.
- MySQL에서 PK를 제외한 모든 인덱스는 PK를 가지고 있다.
클러스터 키 | 데이터 주소 |
---|---|
1 | A |
2 | B |
3 | C |
4 | E |
이렇게 있다고 가정할때 클러스터 키 4번이 INSERT되면 기존 4번뒷자리들이 한칸씩 일리고 4번이 들어온다.
클러스터 키 | 데이터 주소 |
---|---|
1 | A |
2 | B |
3 | C |
4 | D |
5 | E |
따라서 클러스터 키 삽입/ 갱신시에 성능이슈가 발생한다.
따라서 2번 MySQL에서 PK는 클러스터 인덱스 이기 때문에 PK 삽입/ 갱신시 성능이슈 발생한다.
3번 MySQL에서 PK를 제외한 모든 인덱스는 PK를 가지고 있다. 이 말은 MySQL은 PK가 클러스터 인덱스이기때문에 PK값이 추가되거나 변경되는 경우 만약 다른 인덱스들이 데이터주소를 직접적으로 들고있으면 다른 인덱스들의 값도 전부 바뀌어야하므로 부하가 걸린다.
따라서 다른 인덱스들이 데이터 주소가 아닌 PK를 들고있으므로 인해 PK값이 변경할때 별 상관없이 PK를 들고만 있으면 된다.
다라서 세컨더리 인덱스만으로는 데이터를 찾아갈 수 없다.
- 클러스터 인덱스 장점
- PK를 활용한 검색이 빠르다. 특히 범위검색.
- 세컨더리 인덱스들이 PK를 가지고있어 커버링에 유리하다.
UUID VS Auto Increment
- 장점
- UUID
- 분산 시스템에 유리하다.
- 각각의 값이 사실상 유일하기때문.
- 개발 환경에 독립적이다.
- 분산 시스템에 유리하다.
- Auto Increment
- 빠르다.
- 사람이 볼때 눈이 편하다.
- UUID
- 단점
- UUID
- 성능저하가 크다.
- 눈으로 보기 힘들다.
- 필요 이상으로 공간을 많이 차지한다.
- Auto Increment
- 분산 시스템에 부적합하다.
- UUID
인덱스 사용시 주의사항
- 인덱스 필드 가공
- 인덱스를 가공하면 정상적으로 인덱스를 사용해야하는지 옵티마이저는 판단하지 못한다.
- ex) Int타입인 인덱스를 String타입으로 비교한다거나 인덱스 컬럼을 index * 2 처럼 가공한다거나.
- 인덱스를 가공하면 정상적으로 인덱스를 사용해야하는지 옵티마이저는 판단하지 못한다.
- 복합 인덱스
- 선두 컬럼의 인덱스를 기준으로 정렬되고 그 다음 인덱스가 정렬되기 때문에 해당 인덱스는 전체적으로 정렬된 모양이 아니기 때문에 선구컬럼의 인덱스가 중요하다.
- 하나의 쿼리에는 하나의 인덱스만
- 따라서 WHERE, ORDER BY, GROUP BY 혼합해서 사용할 때에는 인덱스를 잘 고려해야함.
- 의도대로 인덱스가 동작하지 않을경우엔 explain으로 확인하자
- 익덱스도 비용 -> 쓰기를 희생하고 조회를 얻는다.
- 꼭 인덱스로만 해결할 수 있는 문제인가?
인덱스를 모든 컬럼에 걸어두면 좋은거 아닐까?
- 위에 써났듯이 결국 인덱스도 비용이기 때문에 저장공간이 많이 늘어나고 INSERT시 성능이 부족해진다.
인텍스 설정 기준
- 카디널리티
- 선택도
- 활용도
- 중복도
카디널리티가 높을 수록 인덱스 설정에 좋은 컬럼이다.
= 컬럼이 갖고있는 값의 중복정도가 낮을수록 좋다.
예를들어 0과 1뿐인 컬럼은 하나를 걸러내도 나머지 절반이 남아있기 때문에..
'대용량 처리 이해 > Mysql' 카테고리의 다른 글
페이지네이션 최적화 (1) | 2022.12.25 |
---|---|
정규화 (0) | 2022.12.24 |
데이터베이스 성능 (0) | 2022.12.22 |
정규화 (0) | 2022.12.21 |
대용량 시스템에 대한 이해 (0) | 2022.12.12 |