Replies: 2 comments
-
|
인덱스는 책의 목차같은 개념으로, DB에 저장된 데이터를 쉽게 찾을수있도록 돕습니다. 제가 생각하는 인덱스 사용 이유는 추가적으로 인덱스 사용 시 어디서 빠른 속도의 이점을 얻을 수 있는 지 찾아보았습니다.
또한 인덱스는 기본 테이블 데이터 말고도 추가로 데이터가 저장되며, Btree 구조로 형성됩니다. Btree는 자식 노드를 따라 범위를 점점 좁혀가서 타겟을 찾아내고, 자식 노드끼리 양방향으로 연결되어있어서 Range Scan에도 성능이 좋습니다. 다만, 기본적으로 페이지 단위 저장이기 때문에, 꽉차게 되는 경우 트리를 재구성하게 되는 불편함이 존재합니다. |
Beta Was this translation helpful? Give feedback.
-
|
저는 DB 인덱스를 "테이블에서 원하는 데이터를 빠르게 찾기 위해 별도로 유지하는 정렬된 자료구조"라고 이해했습니다. 다만 인덱스는 공짜가 아니라 읽기 성능과 쓰기 성능, 저장 공간 사이의 트레이드오프를 가지는 도구이고, 1. 인덱스란 무엇인가인덱스는 테이블의 특정 컬럼에 대해 별도로 만들어둔 정렬된 자료구조입니다. 책의 뒷부분에 있는 색인(index)을 생각하면 직관적입니다. 책에서 "트랜잭션"이라는 단어가 나오는 페이지를 찾고 싶을 때, 처음부터 끝까지 한 장씩 넘기지 않습니다. 색인을 펼쳐서 "ㅌ" 항목에서 "트랜잭션 → 245p, 312p"를 확인하고 해당 페이지로 바로 갑니다. DB도 마찬가지입니다. 인덱스가 없으면 테이블 전체를 순차적으로 읽어가며 조건에 맞는 행을 찾아야 하는데(Full Table Scan), 이는 데이터가 많을수록 비례해서 느려집니다. 인덱스가 있으면 정렬된 자료구조를 이용해 원하는 행의 위치를 빠르게 찾아갈 수 있습니다. 중요한 점: 인덱스는 원본 테이블의 일부가 아니라 별도로 존재하는 보조 자료구조입니다. 그래서 인덱스를 만들면 추가 저장 공간이 필요하고, 데이터가 변경될 때 인덱스도 함께 갱신해야 합니다. 2. 인덱스를 사용하는 이유(a) 조회 성능 향상 가장 직접적인 이유입니다. 100만 건의 예약 데이터에서 특정 회원의 예약을 찾는다고 가정하면,
데이터 양이 늘어날수록 차이가 극적으로 커집니다. (b) 정렬 비용 절감
(c) 유일성 보장 (Unique Index)
(d) 조인 성능 향상 조인 조건의 컬럼에 인덱스가 있으면 조인 알고리즘(특히 Nested Loop Join)이 훨씬 효율적으로 동작합니다. 외래키 컬럼에 인덱스가 자주 걸리는 이유가 여기에 있습니다. 3. 인덱스는 어떻게 동작하는가B-Tree 인덱스가 기본 대부분의 RDBMS는 인덱스로 B-Tree(정확히는 B+Tree) 를 사용합니다. 왜 단순한 이진 탐색 트리나 해시가 아닌 B-Tree냐 하면, 디스크 I/O 특성에 최적화되어 있기 때문입니다. B-Tree의 핵심 특징:
예를 들어 100만 건 데이터의 B-Tree 인덱스 높이는 보통 3 정도입니다. 조회 흐름
이 마지막 단계를 "테이블 lookup" 이라고 부르는데, 이게 한 번 더 발생하기 때문에 인덱스가 항상 빠른 건 아닙니다. 조회할 행이 너무 많으면(예: 전체의 30% 이상) 차라리 Full Table Scan이 더 빠른 경우도 있습니다. 옵티마이저는 이런 비용을 계산해서 인덱스 사용 여부를 결정합니다. 쓰기 시 동작
그래서 인덱스를 많이 만들수록 조회는 빨라지지만 쓰기는 느려지는 트레이드오프가 생깁니다. 4. 인덱스의 트레이드오프저는 인덱스를 다룰 때 가장 중요한 게 "인덱스는 공짜가 아니다" 라는 인식이라고 생각합니다. 비용 1. 추가 저장 공간 인덱스는 별도 자료구조이므로 디스크 공간을 차지합니다. 인덱스가 많은 테이블은 데이터 자체보다 인덱스가 더 큰 경우도 있습니다. 비용 2. 쓰기 성능 저하 위에서 언급한 것처럼 INSERT/UPDATE/DELETE 시 모든 관련 인덱스가 갱신되어야 합니다. 특히 자주 변경되는 컬럼에 인덱스를 걸면 쓰기 성능이 눈에 띄게 떨어질 수 있습니다. 비용 3. 옵티마이저 판단 비용 인덱스가 많아질수록 옵티마이저가 어떤 인덱스를 쓸지 판단하는 비용도 늘어납니다. 드문 경우지만 인덱스가 너무 많으면 옵티마이저가 잘못된 인덱스를 선택할 수도 있습니다. 그래서 판단 기준은
5. 인덱스가 동작하지 않는 경우인덱스를 걸어도 실제로 사용되지 않는 경우가 자주 있습니다. 저는 이걸 모르고 인덱스만 추가하면 성능 문제가 해결될 거라 기대하는 게 가장 흔한 함정이라고 생각합니다. (a) 컬럼에 함수/연산이 적용된 경우 -- 인덱스가 동작하지 않음
SELECT * FROM reservation WHERE YEAR(date) = 2026;
-- 인덱스가 동작함
SELECT * FROM reservation WHERE date BETWEEN '2026-01-01' AND '2026-12-31';(b) LIKE의 와일드카드가 앞에 있는 경우 -- 인덱스가 동작하지 않음
SELECT * FROM member WHERE name LIKE '%kim';
-- 인덱스가 동작함
SELECT * FROM member WHERE name LIKE 'kim%';(c) 복합 인덱스의 순서 문제
-- 인덱스가 잘 동작함 (앞에서부터 매칭)
WHERE date = '2026-05-27' AND time_id = 1
-- 인덱스가 부분적으로만 동작하거나 못 함 (date 없이 사용)
WHERE time_id = 1 AND theme_id = 3복합 인덱스는 "왼쪽부터 순서대로" 사용될 때만 효과적입니다. 이 원칙을 leftmost prefix rule이라고 부릅니다. (d) 타입이 맞지 않는 비교 -- member_id가 BIGINT인데 문자열로 비교 → 인덱스가 동작하지 않을 수 있음
WHERE member_id = '5'이런 함정들이 있어서, 인덱스를 추가한 뒤에는 반드시 6. 미션과 연결지어 보면이번 예약 미션에서 인덱스를 고민할 만한 지점이 몇 군데 있습니다. (a) 중복 예약 방지를 위한 UNIQUE INDEX CREATE UNIQUE INDEX idx_reservation_unique
ON reservation(date, time_id, theme_id)
WHERE status = 'RESERVED';"같은 날짜, 같은 시간, 같은 테마에 예약은 하나만"이라는 규칙을 DB 레벨에서 강제하는 가장 안전한 방법입니다. 이전 격리 수준 토론에서도 정리했듯, 애플리케이션 코드의 검증만으로는 동시성 상황에서 정합성이 깨질 수 있어 DB의 유니크 제약이 최종 방어선이 됩니다. 다만 논리 삭제( (b) 조회 패턴에 따른 인덱스
어떤 API가 자주 호출되는지에 따라 인덱스 전략이 달라집니다. (c) 외래키 컬럼
저의 접근 순서 저는 인덱스를 미리부터 빽빽하게 거는 것보다, "실제로 어떤 쿼리가 느린지 측정 → EXPLAIN으로 실행 계획 확인 → 필요한 인덱스만 추가" 순서가 더 건강하다고 생각합니다. 미션 초반부터 가능한 인덱스를 다 거는 건 오히려 학습에도 좋지 않다고 봅니다. 느린 쿼리를 만나고, 왜 느린지 분석하고, 인덱스로 해결되는 경험이 인덱스의 본질을 가장 잘 가르쳐준다고 생각합니다. 7. 정리저는 인덱스를 이렇게 정리할 수 있을 것 같습니다.
핵심 요점:
결론적으로 인덱스를 잘 다루는 능력은 "어떤 컬럼에 인덱스를 걸까" 보다 "이 쿼리가 왜 느린지 진단하고, 인덱스가 해결책인지 판단하고, EXPLAIN으로 검증하는 능력" 에 가깝다고 생각합니다. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
에 대해 간단히 작성해주세요
Beta Was this translation helpful? Give feedback.
All reactions