데이터베이스 & ORM
PostgreSQL GIN
DoRightting
2024. 11. 10. 19:57
1. GIN(Generalized Inverted Index) 개요
GIN 인덱스 사용 예시
-- 프롬프트의 키워드와 카테고리 검색을 위한 GIN 인덱스
CREATE INDEX idx_config ON prompts USING GIN (config);
-- 벡터 유사도 검색을 위한 인덱스
CREATE INDEX prompt_vector_idx ON prompts
USING ivfflat (embedding_vector vector_l2_ops)
WITH (lists = 100);
1.1 GIN의 특징
- 다중 값 데이터 타입 처리
- JSONB
- 배열
- 전문 검색(Full-text search)
- 구조
- 키 -> 포스팅 리스트(해당 키가 출현하는 행들의 목록)
- B-tree와 달리 하나의 열이 여러 키를 가질 수 있음
2. 프로젝트 내 GIN 인덱스 활용
2.1 JSONB 데이터 검색
@Entity
@Table(name = "prompts")
public class Prompt {
@Type(JsonBType.class)
@Column(columnDefinition = "jsonb")
private Map<String, List<String>> categoryKeywords;
}
// 인덱스 생성
@Query(value = """
CREATE INDEX IF NOT EXISTS idx_category_keywords
ON prompts USING GIN (category_keywords)
""", nativeQuery = true)
2.2 검색 쿼리 예시
-- 특정 키워드를 포함하는 프롬프트 검색
SELECT * FROM prompts
WHERE category_keywords @> '{"art_style": ["digital art"]}'::jsonb;
-- 여러 조건을 조합한 검색
SELECT * FROM prompts
WHERE category_keywords @> '{"medium": ["painting"]}'
AND category_keywords ? 'color_scheme';
GIN 인덱스를 선택한 이유
- 데이터 특성
- 다중 값을 가진 JSONB 데이터 저장
- 효율적인 키워드 검색 필요
- // 프롬프트의 카테고리와 키워드는 JSONB 형태로 저장 @Column(columnDefinition = "jsonb") private Map<String, List<String>> categoryKeywords;
- 검색 성능
- 전문 검색 지원
- 복잡한 검색 조건에서도 높은 성능 제공
B-tree 대신 GIN을 사용했을 때의 장단점
- 장점
- 다중 값 데이터의 효율적인 검색
- 부분 일치 검색 성능 우수
- -- GIN의 효율적인 포함 검사 WHERE category_keywords @> '{"style": ["modern"]}'
- 단점
- 인덱스 크기가 더 클 수 있음
- 삽입 성능이 상대적으로 느릴 수 있음
GIN 인덱스의 성능 최적화
- 인덱스 설정
- fastupdate 옵션 활용
- 주기적인 VACUUM ANALYZE 수행
- -- 빠른 갱신을 위한 fastupdate 옵션 CREATE INDEX idx_category_keywords ON prompts USING GIN (category_keywords) WITH (fastupdate = on);
- 쿼리 최적화
- 적절한 연산자 선택
- 실행 계획 분석
- -- 효율적인 연산자 사용 WHERE category_keywords @> '{"key": "value"}' -- 대신 WHERE category_keywords->>'key' = 'value'
GIN 인덱스 관리
- 모니터링
- 인덱스 크기 추적
- 사용 패턴 분석
- -- 인덱스 크기 및 사용량 모니터링 SELECT schemaname, tablename, indexname, indexdef FROM pg_indexes WHERE indexname = 'idx_category_keywords';
- 유지보수
- 주기적인 VACUUM
- 통계 정보 업데이트
- -- 정기적인 인덱스 관리 VACUUM ANALYZE prompts;
GIN 인덱스 사용 시 주의할 점
- 리소스 관리
- 적절한 메모리 할당
- 디스크 공간 모니터링
- -- 작업 메모리 설정 SET maintenance_work_mem = '1GB';
- 성능 고려사항
- 대량 데이터 처리 전략
- 인덱스 재생성 타이밍
- // 대량 데이터 입력 시 인덱스 재생성 고려 @Transactional public void bulkInsert(List<Prompt> prompts) { // 인덱스 삭제 후 데이터 입력하고 인덱스 재생성 }
GIN과 다른 인덱스 타입과의 조합 결정 근거
- 데이터 특성 분석
- 검색 패턴 분석
- 데이터 타입별 최적 인덱스 선택
- -- 데이터 특성에 따른 인덱스 선택 CREATE INDEX idx_category_keywords USING GIN (...); -- JSONB 데이터 CREATE INDEX idx_created_at USING BTREE (...); -- 날짜 데이터
- 쿼리 패턴
- 자주 사용되는 쿼리 분석
- 복합 인덱스 고려