자, PostgreSQL 세계에는 여러 가지 인덱스가 있고, 각각 자기만의 역할이 있어. 이건 마치 교통수단 고르는 거랑 비슷해. 공원 산책할 땐 자전거가 좋지만, 도시 반대편 갈 땐 차를 타겠지? 인덱스도 마찬가지로, 상황에 따라 맞는 걸 골라야 해.
PostgreSQL에서 주요 인덱스 종류는 다음과 같아:
B-TREE인덱스: 대부분의 상황에 쓸 수 있는 범용 인덱스.HASH인덱스: 정확한 값 비교에 최적화됨.GIN인덱스: 배열이나 JSONB 검색에 딱임.GiST인덱스: 지리 정보 같은 복잡한 데이터 타입에 사용됨.
인덱스는 행 검색을 빠르게 하려고 만들어진 거야. 최적화 방식이 4가지나 있는데, 각 타입마다 특정 작업에 더 빠르고, 특정 데이터 타입에 더 잘 맞아.
인덱스를 직접 관리할 수는 없어. 네가 할 수 있는 건 인덱스 타입을 고르는 것뿐이야: 아예 안 쓰거나, 위에 나온 것 중 하나를 쓰거나. 이제 각각을 하나씩 파보자. 언제, 어떻게 써야 하는지 감 잡을 수 있을 거야.
B-TREE 인덱스
B-TREE (balanced tree의 줄임말)는 PostgreSQL에서 제일 많이 쓰이는 인덱스야. 이 인덱스는 트리 구조로 데이터를 정리해서, 검색이나 정렬, 필터링을 빠르게 해줘.
도서관 책장이 있다고 생각해봐. 각 책장에는 책이 가나다순으로 정렬돼 있어. "ㅁ"으로 시작하는 책을 찾으려면 모든 책을 다 볼 필요 없이, 중간부터 시작하면 돼. B-TREE도 이런 원리로 동작해.
언제 쓰면 좋을까?
거의 항상! B-TREE 인덱스는 특히 이런 데 좋아:
- 범위 검색:
WHERE price > 100 - 정렬:
ORDER BY name ASC - 정확한 값 검색:
WHERE id = 42
예시로 만들어보자:
-- products 테이블의 price 컬럼에 B-TREE 인덱스 생성:
CREATE INDEX idx_price ON products(price);
이제 WHERE price > 100 같은 쿼리를 쓰면, PostgreSQL이 이 인덱스를 활용해서 전체 테이블을 다 뒤지지 않아도 돼.
HASH 인덱스
HASH 인덱스는 해시 테이블을 써서 빠르게 값을 찾는 방식이야. 정확히 일치하는 값 비교에 강점이 있어. 하지만 HASH 인덱스는 범위 검색이나 정렬은 지원하지 않아.
이건 마치 도서관 카드 파일에서, 각 카드에 번호가 딱 붙어 있는 거랑 비슷해. 42번 카드를 찾으라고 하면 바로 찾아주지만, "40번부터 50번까지 보여줘"라고 하면 못 해줘.
HASH 인덱스는 오직 정확한 값 검색에만 써:
WHERE email = 'user@example.com'SELECT ... WHERE id = 123
범위나 정렬이 필요하면 HASH는 안 맞아.
생성 예시:
-- users 테이블의 email 컬럼에 해시 인덱스 생성:
CREATE INDEX idx_email_hash ON users USING HASH (email);
이제 PostgreSQL은 WHERE email = 'user@example.com' 같은 쿼리에 이 인덱스를 쓸 거야.
참고: HASH 인덱스는 특정 상황에서만 쓰이고, B-TREE보다 덜 자주 사용돼.
GIN 인덱스 (Generalized Inverted Index)
GIN은 배열, JSONB, 텍스트 데이터에 진짜 마법을 부리는 특수 인덱스야. 수천 개의 서랍이 있는 캐비닛을 상상해봐. 각 서랍엔 라벨이 붙어 있고, "사과" 서랍엔 사과만, "바나나" 서랍엔 바나나만 들어 있어. 사과나 바나나를 찾으려면 모든 서랍을 뒤질 필요 없이 바로 해당 서랍으로 가면 돼.
GIN 인덱스는 이런 데 필요해:
- 배열 검색:
@>(포함),<@(포함됨) - JSONB 데이터:
WHERE jsonb_data @> '{"key": "value"}'
생성 예시
-- 배열을 담고 있는 products 테이블의 tags 컬럼에 GIN 인덱스 생성:
CREATE INDEX idx_tags_gin ON products USING GIN (tags);
이제 PostgreSQL은 "전자제품"이나 "추천" 같은 태그가 들어간 상품을 빠르게 찾을 수 있어.
GiST 인덱스 (Generalized Search Tree)
GiST 인덱스는 지리 좌표나 범위 같은 복잡한 데이터 타입에 강력한 도구야. 공간 검색이나 범위 검색에 최적화된 트리를 만들어줘.
도시 지도를 생각해봐. 각 지점이 좌표로 표시돼 있고, 현재 위치에서 반경 5km 안에 있는 모든 지점을 빠르게 찾을 수 있어.
GiST는 이런 데 좋아:
- 지리 데이터:
SELECT ... FROM locations WHERE ST_DWithin(geom, point, distance) - 범위 검색:
WHERE date_range && '[2023-01-01, 2023-12-31]'
예시:
-- 지리 데이터를 담고 있는 places 테이블의 location 컬럼에 GiST 인덱스 생성:
CREATE INDEX idx_location_gist ON places USING GiST (location);
이제 가까운 지점을 찾는 등 복잡한 지리 쿼리를 할 수 있어.
인덱스 비교 표
| 인덱스 타입 | 적합한 용도 | 사용 예시 | 비고 |
|---|---|---|---|
B-TREE |
범위 검색, 정렬 | price > 100, ORDER BY name ASC |
범용 인덱스. |
HASH |
정확한 값 비교 | email = 'user@example.com', id = 42 |
범위 검색 불가. |
GIN |
배열, JSONB | tags @> '{tech}', jsonb_data @> '{"key": "value"}' |
복잡한 데이터에 더 빠름. |
GiST |
지리, 범위, 거리 | ST_DWithin(geom, point, distance) |
지리 데이터에 사용. |
이제 PostgreSQL의 주요 인덱스 타입과 그 활용법을 알게 됐어. 인덱스 선택은 전략적인 한 수야. 쿼리 속도가 여기서 갈리거든. 체스에서 체크메이트 치듯, 느린 쿼리도 끝!
GO TO FULL VERSION