2026/06/06 8

Ch07. 인덱스 - 인덱스의 단점과 주의사항

인덱스는 공짜가 아니다( 인덱스의 단점)저장 공간 (Storage)인덱스는 원본 테이블과는 별개로, B-Tree 구조를 가진 물리적인 파일로 디스크에 저장된다.즉, 인덱스를 생성하면 그만큼의 추가 저장 공간이 필요하다.인덱스는 어떻게 구성하는지에 따라 다르지만, 일반적으로 원본 테이블 크기의 약 10% 내외의 공간을 추가로 차지한다고 알려져 있다. 만약 100GB에 달하는 거대한 items 테이블이 있고, 여기에 5개의 인덱스를 추가로 생성한다면? 인덱스만으로 약 50GB라는 무시할 수 없는 추가 디스크 공간이 필요하게 된다. 인덱스를 무분별하게 생성하면 디스크 사용량이 계속해서 늘어나는 것을 보게 될 것이다. 쓰기 성능 (INSERT, UPDATE, DELETE)인덱스는 "SELECT"의 속도를 높이는..

Ch07. 인덱스 - 인덱스 설계 가이드라인

인덱스를 만드는 법(CREATE INDEX)을 아는 것보다 더 중요한 것은, 어디에 인덱스를 만들어야 하는지 아는 것이다. 잘못된 인덱스는 오히려 시스템 성능을 떨어뜨리는 애물단지가 될 수 있다 인덱스는 결코 공짜가 아니다. 데이터를 추가(INSERT), 수정(UPDATE), 삭제(DELETE)할 때마다 인덱스도 함께 변경되어야 하므로 쓰기 성능이 저하되고, 별도의 저장 공간도 차지한다. 따라서 우리는 이 비용을 상쇄하고도 남을 만큼의 "검색 성능 향상"이라는 이득을 얻을 수 있는 곳에만 전략적으로 인덱스를 생성해야 한다. 핵심 원칙: 카디널리티 (Cardinality)인덱스를 어디에 걸지 판단하는 가장 중요한 기준은 바로 카디널리티(Cardinality)다. 카디널리티란, 해당 컬럼에 저장된 값들의 고..

Ch07. 인덱스 - 복합 인덱스(1)

"카테고리가 '전자기기'인 상품들 중에 가격이 100,000원 이상인 상품을 보여줘" 이러한 요구사항이 들어왔다.SELECT * FROM itemsWHERE category = '전자기기' AND price >= 100000 다중 조건 쿼리의 성능을 최적화하기 위해 사용하는 것이 바로 복합 인덱스(Composite Index) 또는 다중 컬럼 인덱스(Multi-column Index)다.복합 인덱스는 이름 그대로 두 개 이상의 컬럼을 묶어서 하나의 인덱스로 만드는 것이다하지만 복합 인덱스를 제대로 사용하려면 한 가지 매우 중요한 규칙을 이해해야 한다. 바로 "컬럼의 순서"다왜 컬럼 순서가 중요할까?복합 인덱스의 동작 원리는 우리가 실생활에서 사용하는 "전화번호부"나 "국어사전"과 똑같다.전화번호부: "..

Ch07. 인덱스 - 커버링 인덱스

커버링 인덱스는 "쿼리에 필요한 모든 컬럼을 포함하고 있는 인덱스"를 말한다. "커버링"이라는 이름 그대로, 인덱스 하나가 쿼리의 요구사항 전체를 "덮는다"는 의미다. 데이터베이스 옵티마이저는 쿼리를 실행할 때, 만약 특정 인덱스가 "SELECT" , "WHERE" , "ORDER BY" , "GROUP BY" 절에 사용되는 모든 컬럼을 가지고 있다면, 원본 테이블에 전혀 접근하지 않고 오직 인덱스만을 읽어서 쿼리를 처리한다. 이는 디스크의 여러 곳을 오가는 비싼 랜덤 I/O 작업을 완전히 제거하고, 순차 I/O에 가까운 인덱스 스캔만으로 쿼리를 끝낼 수 있음을 의미한다. 당연히 성능은 비약적으로 향상된다. 예시: 커버링 인덱스의 적용 전과 후쇼핑몰에서 가격이 50,000원에서 100,000원 사이인 상..

Ch07. 인덱스 - 옵티마이저와 인덱스 선택

컬럼에 인덱스를 생성하면, 해당 컬럼을 조건으로 사용하는 모든 "WHERE"절의 성능이 향상될 것이라고 기대하기 쉽다. 하지만 항상 그렇지는 않다. 데이터베이스의 "옵티마이저(Optimizer)"는 쿼리를 실행하기 전에 여러 실행 가능한 방법을 평가하고, 그중 가장 비용이 적게 드는, 즉 가장 효율적이라고 판단되는 방법을 선택한다. 이 과정에서 옵티마이저는 "인덱스를 사용하는 것이 오히려 비효율적이라고 판단"하면, 인덱스가 존재하더라도 과감히 포기하고 "테이블 전체를 스캔(Full Table Scan)"하는 방법을 선택할 수 있다. 인덱스를 사용하면 검색 대상의 양은 줄어들지만, items 테이블의 여러 위치에 흩어진 데이터에 랜덤 하게 접근해야 한다. 예를 들어, "19, 6, 3, 14, 8"번 행 ..

Ch07. 인덱스 - 인덱스와 정렬

데이터베이스에서 정렬(ORDER BY) 작업은 생각보다 비용이 많이 드는 무거운 작업 중 하나다. 왜냐하면 조건에 맞는 데이터를 모두 찾은 후에, 그 결과를 서로 비교하면서 순서에 맞게 다시 정렬해야 하기 때문이다. 찾은 데이터가 수십, 수백만 건이라면 이 데이터를 정렬 알고리즘을 사용해서 정렬해야 하는데, 이 정렬 과정에서 엄청난 부하가 발생할 수 있다. 하지만 우리에게는 인덱스가 있다. 인덱스는 이미 데이터가 특정 순서로 정렬된 자료구조다. 그렇다면 이 정렬된 인덱스를 활용해서 "ORDER BY" 작업의 성능을 획기적으로 개선할 수 있지 않을까? "ORDER BY"가 인덱스를 잘 활용하면, 별도의 정렬 과정 없이 이미 정렬된 인덱스를 순서대로 읽기만 하면 되므로 매우 빠르게 동작한다. 데이터베이스는 ..

Ch07. 인덱스 - 인덱스와 LIKE 범위 검색

"LIKE"절에서 인덱스를 사용하려면, 와일드카드(%)가 검색어의 뒤쪽에 위치해야 한다. "WHERE item_name LIKE '게이밍%'" : 인덱스 사용 가능(O)"WHERE item_name LIKE '% 게이밍'" : 인덱스 사용 불가 (X)"WHERE item_name LIKE '%게이밍%'" : 인덱스 사용 불가 (X)"%"가 앞에 있으면 시작점이 불분명해져 정렬된 인덱스를 활용할 수 없기 때문이다. LIKE 검색 성공 예제: 와일드카드(%)가 뒤에 오는 경우"상품 이름이 '게이밍'으로 시작하는 모든 상품을 찾아보자."select * from items where item_name like '게이밍%'이 쿼리는 와일드카드(%)가 검색어 뒤에 붙어있으므로, "item_name"으로 정렬된 인..

Ch07. 인덱스 - 인덱스와 범위 검색

items 테이블의 "price" 컬럼을 사용하여 범위 검색(BETWEEN)에 인덱스가 어떻게 사용되는지 EXPLAIN으로 확인해 보자. explain select * from items where price between 50000 and 100000;type(ALL): 풀 테이블 스캔이 발생했다.데이터베이스는 "price"가 50000에서 100000 사이인 상품을 찾기 위해 items 테이블의 모든 상품 데이터를 처음부터 끝까지 하나씩 확인해야만 한다.key(NULL): price 컬럼을 조건으로 사용했지만, 이 컬럼에는 인덱스가 없으므로 사용된 인덱스가 없다는 의미의 "NULL"이 표시된다.rows(25): 테이블의 전체 행 수인 "25"가 표시된다. 풀 테이블 스캔을 하므로 당연한 결과다. (예..