인덱스 유형 알아보기
인덱스 유형 알아보기 (Index Types)
PostgreSQL이 지원하는 인덱스 유형은 꽤 다양해요. B-tree 하나만 있는 게 아니라 상황에 따라 골라 쓸 수 있는 여러 종류가 있죠. 이 페이지에서는 각 인덱스 유형이 어떤 원리로 동작하고, 어떤 쿼리에 강한지 정리해 볼게요.
출처: 공식문서
인덱스 유형 목록과 기본값
PostgreSQL은 B-tree, Hash, GiST, SP-GiST, GIN, BRIN 그리고 확장 모듈 bloom까지 여러 인덱스 유형을 제공해요. 각 유형은 서로 다른 알고리즘을 쓰기 때문에, 어떤 종류의 인덱스 가능 절(indexable clause)에 가장 적합한지도 달라져요.
기본적으로 CREATE INDEX 명령은 B-tree 인덱스를 만들어요. 이게 가장 흔한 상황에 잘 맞죠. 다른 유형은 USING 키워드 뒤에 인덱스 유형 이름을 적어 선택해요. 가령 Hash 인덱스를 만들려면 이렇게 해요.
CREATE INDEX name ON table USING HASH (column);
B-Tree 인덱스
B-tree는 어떤 순서로 정렬할 수 있는 데이터에 대한 동등(equality) 및 범위(range) 쿼리를 처리할 수 있어요. 특히 쿼리 플래너는 인덱스 컬럼이 아래 연산자 중 하나로 비교에 관여할 때 B-tree 인덱스를 고려해요.
< <= = >= >
BETWEEN 이나 IN 처럼 이 연산자들을 조합한 형태도 B-tree 인덱스 검색으로 구현할 수 있어요. 또 인덱스 컬럼에 대한 IS NULL / IS NOT NULL 조건도 B-tree 인덱스와 함께 쓸 수 있죠.
최적화기는 패턴 매칭 연산자 LIKE 와 ~ 를 쓰는 쿼리에서도 B-tree 인덱스를 쓸 수 있는데, 패턴이 상수이고 문자열의 시작 부분에 고정돼 있을 때예요. 예를 들어 col LIKE 'foo%' 나 col ~ '^foo' 는 가능하지만 col LIKE '%bar' 는 아니에요. 다만 DB가 C 로케일을 쓰지 않으면 패턴 매칭 쿼리를 지원하는 특별한 연산자 클래스로 인덱스를 만들어야 해요. ILIKE 와 ~* 도 B-tree 인덱스를 쓸 수 있지만, 패턴이 대소문자 변환의 영향을 받지 않는 비알파벳 문자로 시작할 때만 가능해요.
B-tree 인덱스는 데이터를 정렬된 순서로 가져오는 데도 쓸 수 있어요. 단순 스캔 후 정렬보다 항상 빠른 건 아니지만, 자주 도움이 되죠.
Hash 인덱스
Hash 인덱스는 인덱스 컬럼 값에서 유도한 32비트 해시 코드를 저장해요. 그래서 이 인덱스는 단순한 동등 비교만 처리할 수 있어요. 쿼리 플래너는 인덱스 컬럼이 등호 연산자를 쓰는 비교에 관여할 때 Hash 인덱스를 고려해요.
=
GiST 인덱스
GiST 인덱스는 단일한 인덱스 종류가 아니라, 다양한 인덱싱 전략을 구현할 수 있는 인프라스트럭처예요. 그래서 GiST 인덱스에 쓸 수 있는 특정 연산자는 사용하는 인덱싱 전략(연산자 클래스)에 따라 달라져요. 예를 들어 표준 PostgreSQL 배포본에는 여러 2차원 기하학 데이터 타입용 GiST 연산자 클래스가 포함돼 있고, 아래 연산자를 쓰는 인덱스 쿼리를 지원해요.
<< &< &> >> <<| &<| |&> |>> @> <@ ~= &&
GiST 인덱스는 "최근접 이웃(nearest-neighbor)" 검색도 최적화할 수 있어요. 예를 들어 아래 쿼리는 주어진 목표 점에 가장 가까운 10곳을 찾아줘요.
SELECT * FROM places ORDER BY location <-> point '(101,456)' LIMIT 10;
이 역시 사용하는 연산자 클래스에 따라 가능 여부가 달라지고, 이렇게 쓸 수 있는 연산자들은 연산자 클래스 테이블의 "Ordering Operators" 컬럼에 나열돼 있어요.
SP-GiST 인덱스
SP-GiST 인덱스는 GiST처럼 다양한 종류의 검색을 지원하는 인프라를 제공해요. SP-GiST는 쿼드트리(quadtree), k-d 트리, radix 트리(trie) 같은 다양한 비균형 디스크 기반 데이터 구조를 구현할 수 있게 해줘요. 표준 배포본에는 2차원 점(point)용 SP-GiST 연산자 클래스가 포함돼 있고, 아래 연산자를 쓰는 인덱스 쿼리를 지원해요.
<< >> ~= <@ <<| |>>
GiST처럼 SP-GiST도 "최근접 이웃" 검색을 지원해요. 거리 순서를 지원하는 SP-GiST 연산자 클래스에서는 해당 연산자가 "Ordering Operators" 컬럼에 나열돼 있어요.
GIN 인덱스
GIN 인덱스는 "역색인(inverted index)"이에요. 배열처럼 여러 컴포넌트 값을 담을 수 있는 데이터 값에 적합하죠. 역색인은 각 컴포넌트 값마다 별도의 항목을 갖고 있어서, 특정 컴포넌트 값의 존재를 확인하는 쿼리를 효율적으로 처리해요.
GiST·SP-GiST와 마찬가지로 GIN도 다양한 사용자 정의 인덱싱 전략을 지원하고, 사용 가능한 연산자는 인덱싱 전략에 따라 달라져요. 표준 배포본에는 배열용 GIN 연산자 클래스가 포함돼 있고, 아래 연산자를 쓰는 인덱스 쿼리를 지원해요.
<@ @> = &&
BRIN 인덱스
BRIN(Block Range INdexes) 인덱스는 테이블의 연속된 물리적 블록 범위에 저장된 값에 대한 요약(summary)을 저장해요. 그래서 컬럼 값이 테이블 행의 물리적 순서와 잘 연관돼 있을 때 가장 효과적이죠. GiST·SP-GiST·GIN처럼 BRIN도 다양한 인덱싱 전략을 지원하는데, 선형 정렬 순서를 가진 데이터 타입에서는 인덱스된 데이터가 각 블록 범위에 대한 컬럼 값의 최솟값·최댓값에 해당해요. 이걸로 아래 연산자를 쓰는 인덱스 쿼리를 지원해요.
< <= = >= >