Boolean 컬럼 인덱스와 Cardinality에 따른 실행 계획에 대하여
강의를 듣다가 궁금한 부분이 있어 질문드립니다!
Secondary Index를 사용하면 Primary(Clustering) Index Lookup 과정에서 랜덤 I/O가 발생할 수 있다고 이해하고 있습니다
다만 이는 Cardinality가 낮은 Boolean 컬럼에만 국한된 문제라기보다는, Secondary Index의 정렬 순서와 PK 순서가 일치하지 않는 경우 일반적으로 발생할 수 있는 문제라고 생각합니다
또한 MySQL에서는 MRR을 통해 조회 대상 PK를 정렬한 뒤 접근함으로써 랜덤 I/O를 줄일 수도 있는 것으로 알고 있습니다
강의에서는 Boolean 컬럼의 경우 특정 값이 전체 데이터의 상당 부분을 차지할 가능성이 높기 때문에, MRR을 통한 정렬 및 테이블 Lookup보다 Full Table Scan이 더 효율적일 수 있다는 취지로 설명해주신 것으로 이해했습니다
그렇다면 인덱스의 효율은 Cardinality 자체만으로 결정된다기보다, 실제 값의 분포와 선택도, 예상 조회 행 수, Covering Index 여부, MRR 적용 여부 등의 요인을 함께 고려해 판단한다고 이해해도 될까요?
回答 1
1
안녕하세요, 소준영님!
좋은 질문입니다. 말씀하신 이해가 맞습니다.
강의에서는 카디널리티를 인덱스 효율을 판단하는 대표적인 기준으로 설명했지만, 실제 실행 계획은 값의 분포와 선택도, 예상 조회 행 수, Covering Index 여부, MRR 적용 여부 등을 함께 고려해 결정됩니다.
Boolean 컬럼도 데이터가 한쪽으로 치우쳐 있다면, 소수 값을 조회할 때는 인덱스가 효율적일 수 있습니다. 예를 들어 true가 전체의 0.1%라면 WHERE flag = true에는 인덱스가 유리할 수 있지만, 나머지 99.9%를 조회하는 WHERE flag = false에는 Full Table Scan이 더 유리할 수 있습니다.
또한 같은 선택도라도 조회 대상 행이 PK 순서상 가까운 범위에 모여 있는지, 테이블 전체에 흩어져 있는지에 따라 실제 페이지 접근 비용이 달라질 수 있습니다. 이런 의미에서 Secondary Index 컬럼과 Clustered Index 순서 사이의 correlation도 성능에 영향을 줄 수 있습니다.
정리하면 카디널리티는 절대적인 기준이라기보다 중요한 판단 요소 중 하나이며, 최종적으로는 실제 데이터 분포와 EXPLAIN ANALYZE 결과를 함께 확인하는 것이 가장 정확합니다.
다만, 강의에서는 이를 모두 다루기에 과하다고 생각하여 가장 일반적인 판단 기준인 카디널리티를 대표적으로 설명하였습니다!
1
오.. Correlation에 대해서까지는 생각을 안해봤는데 그렇겠네요 . . !
예를 들어 Auto Increment를 적용하고 있는 PK가 존재하는 테이블에 UUID를 Secondary Index로 두는 경우, v4가 아닌 v7으로 둔다면 성능 향상을 기대할 수 있어보이네요
이건 Disk I/O 과정에서 페이지 단위로 데이터를 가져오기 때문에 Disk I/O를 줄일 수 있고 MRR 과정 자체에서도 정렬 비용을 일부 아낄 수 있다고 생각이 드는데 올바른 추론일까요?
1
네, 전반적인 추론은 맞습니다!
UUID v7은 생성 시간 순서가 반영되기 때문에 Auto Increment PK와 비슷한 순서로 쌓일 가능성이 높습니다. 따라서 UUID 범위 조회 시 함께 조회되는 PK들도 서로 가까울 가능성이 커지고, Clustered Index의 인접한 페이지를 연속해서 읽을 수 있어 Disk I/O 감소를 기대할 수 있습니다.
다만 이런 효과는 단건 조회보다 여러 건을 범위로 조회할 때 더 의미가 큽니다. 또한 MRR은 조회 대상 PK를 별도로 모아 정렬하므로, UUIDv7이 MRR의 정렬 비용까지 직접 줄인다고 단정하기보다는 정렬 이후 실제 데이터 페이지 접근이 더 효율적일 수 있다고 보는 편이 정확합니다.
결국 복잡한 쿼리이거나 많은 데이터를 질의해야하는 경우 실행 계획을 통해 실측을 하시는 것을 권장합니다 :)
76강 2분33초 내용 오류
0
12
0
인덱스 강의 혹은 해당 강의 전 듣어야 하는 사전강의 문의
0
16
2
ordered_at, paid_at 과 같이
0
23
1
기본편 오타 제보 드립니다.
0
31
1
노션링크가 접근되지 않습니다.
0
32
1
[실습] WHERE문이 사용된 SQL문 튜닝하기 - 2
0
51
2
JWT토큰 발급 시, subject 값을 다양하게 넣어서 여러 개의 토큰을 만드는 이유
0
44
2
[실습] 인덱스 직접 설정해보기/성능 측정해보기
0
53
2
docker 마지막 실습(app(flask) + mysql) 연동 과정
1
55
2
테스트 코드 작성 시 DTO 새로 작성하는 이유가 궁금합니다.
0
47
1
물리적 모델링 - 실습 (역정규화) 질문
0
48
2
「김영한의 실전 데이터베이스 - 성능 최적화」
0
57
2
aws 관련 질문드립니다.
1
56
3
어플리케이션 실행 후 에러에 관하여 질문 드립니다.
2
60
2
운영환경에 적용해볼 수 없을때...고민입니다 ㅠㅠ
0
54
1
추가 연습 문제 링크 주세요
0
32
0
용어 사전
0
61
2
개념적 모델링 - 실습
0
36
1
유튜브 시연 영상 추가 기능 강의 업로드 계획
0
28
2
DB 설계와 JPA 관련 질문입니다
0
38
1
관리자 페이지 질문
0
33
2
드랍 테이블로 지운 ordes에 대해서 질문
0
41
1
문제 풀이 1번 질문
0
40
1
twitterdb 연결이 안돼요
1
47
2

