Skip to content

Commit

Permalink
docs(sql-query-index.md): 인덱스 분포도 내용 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
gmoon92 committed May 30, 2024
1 parent 897c6a8 commit 6f79957
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions spring-jpa/doc/sql-query-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ MySQL에서 페이지(Page)는 InnoDB 스토리지 엔진이 데이터를 저장
- 기본 단위: 페이지는 기본적으로 16KB 크기로 동일한 크기로 구성된다.
- 페이지 크기는 서버 설정으로 조정할 수
있다. [MySQL 8.0 innodb file space](https://dev.mysql.com/doc/refman/8.0/en/innodb-file-space.html) 를 참고하자.
- 데이터 저장: 테이블의 행(row), 인덱스, 데이터 딕셔너리 정보를 포함한 다양한 데이터가 페이지 단위로 저장된다.
- 데이터 저장: 테이블의 행(ROW), 인덱스, 데이터 딕셔너리 정보를 포함한 다양한 데이터가 페이지 단위로 저장된다.
- 디스크 I/O 효율성: InnoDB는 디스크 I/O 효율성을 높이기 위해 페이지 단위로 데이터를 읽고 쓴다.
- 한 번에 큰 덩어리의 데이터를 읽고 쓰므로 **디스크 접근 횟수를 줄일 수 있다.**

Expand Down Expand Up @@ -106,9 +106,28 @@ MySQL InnoDB는 시퀀셜 접근과 메모리 효율성을 고려하여, B-tree
### 인덱스 컬럼 선정 기준

- 갱신이 자주되지 않는 컬럼인가?
- 분포도가 좋은 컬럼인가?
- 분포도(selectivity)가 좋은 컬럼인가?
- 분포도는 낮을 수록 좋다. (유니크할 수록 좋다.)
- 조건절에 자주 사용되는 컬럼인가?
- 인덱스 분포도는 쿼리 성능을 좌우하는 중요한 요소다. 분포도가 좋을 수록, 데이터베이스가 쿼리를 처리할 때 필요한 데이터 페이지를 더 적게 읽어도 되므로 성능이 향상된다.
- 인덱스 분포도
- 분포도(%) = 1/(컬럼 값의 종류) * 100
- 분포도(%) = (컬럼 고유 값 ROW 수) / (테이블의 총 ROW 수) * 100
```sql
-- name 컬럼 값 분포도
SELECT COUNT(DISTINCT name) / COUNT(*) * 100 AS index_selectivity
FROM tb_user
```
- 80-90% 이상: 매우 좋음
- 이 경우 인덱스가 대부분의 값들에 대해 고르게 분포되어 있어 쿼리 성능이 최적화된다.
- 60-80%: 여전히 괜찮음
- 이 경우에도 대부분의 쿼리가 효율적으로 수행되지만, 특정 경우에는 성능 저하가 발생할 수 있다.
- 50-60% 이하: 인덱스의 효율성이 떨어질 수 있다.
- 이 경우 특정 값에 데이터가 집중되어 있어 쿼리 성능에 부정적인 영향을 미칠 가능성이 높다.
- 분포도는 괜찮지만 데이터 분포의 불균형이 심하다면 인덱스를 만들지 않는게 나을 수도 있다.
- 예를 들어 테이블 컬럼 수 10개로 구성되어 있고, 전체 row 수 = 1,000 만, 특정 컬럼(`COUNT(DISTINCT column)`) = 10만 이라고 가정하자.
- 수식1 분포도는 10% = 1/10 * 100
- 수식2 분포도는 1% = 10만 / 1,000 만 * 100
- 수식2 분포도를 따져보면 인덱스를 추가했을 시 오히려 오버헤드가 발생될 가능성이 있다.
- 조인절에 연결되어 있는 컬럼인가?
- 정렬에 사용되는 컬럼인가?
- 기본적으로 인덱스를 구성하면 데이터가 정렬되어 저장된다.
Expand Down Expand Up @@ -200,6 +219,11 @@ LIMIT 15 -- no offset
3. `MIN/MAX` 함수를 제외한 모든 집계 함수가 `DISTINCT`를 포함하는 경우
4. `COUNT(*)`가 사용되어선 안 됨
5. 부분 키(`subkey`)의 카디널리티(고유 값의 개수)가 전체 인덱스의 카디널리티보다 100배 작은 경우
9. 인덱스 최적화
- 인덱스 재구성
- `OPTIMIZE TABLE table_name;`
- 테이블 통계 업데이트
- `ANALYZE TABLE table_name;`

## 마무리

Expand Down

0 comments on commit 6f79957

Please sign in to comment.