PostgreSQL 심화 — 트랜잭션·인덱스·JSONB·파티션 · 인덱스 설계 · 퀴즈
퀴즈: 인덱스 설계
문항 8개. 정답과 해설은 풀어 본 뒤에 보여 드립니다.
tenant_id 와 kind 를 **함께** 등호로 거르는 질의가 잦다. 단일 열 인덱스 두 개 대신 복합 인덱스 (tenant_id, kind) 하나가 나은 이유는?
- 단일 열 인덱스는 등호 조건에 아예 쓰이지 못하기 때문
- 복합 인덱스는 쓰기 비용이 단일 열 인덱스보다 낮기 때문
- 두 단일 인덱스는 BitmapAnd 로 합쳐야 하지만 복합 인덱스는 한 번의 스캔으로 끝나기 때문
- 복합 인덱스는 순서와 무관하게 어떤 열 조합에도 쓰이기 때문
복합 인덱스 (tenant_id, kind) 가 있을 때, WHERE kind = 'purchase' 만으로 거르는 질의에서 이 인덱스는?
- 선두 열 tenant_id 가 조건에 없어 효율적인 탐색에 쓰기 어렵다
- kind 가 포함돼 있으므로 항상 최적으로 쓰인다
- 정렬 순서와 무관하게 언제나 순차 스캔이 된다
- kind 를 선두로 재정렬해 자동으로 다시 만든다
status = 'error' 인 행이 전체의 3%뿐이고 이 조건으로만 자주 조회한다. 가장 알맞은 인덱스는?
- status 열 전체에 대한 B 트리 인덱스
- status 를 선두로 한 모든 열의 복합 인덱스
- WHERE status='error' 조건이 붙은 부분 인덱스
- status 에 대한 GIN 인덱스
WHERE lower(user_email) = '...' 로 대소문자 구분 없이 찾는데 email 열의 일반 인덱스가 안 쓰인다. 옳은 해법은?
- email 열에 UNIQUE 제약을 추가한다
- lower(user_email) 표현식 자체에 인덱스를 만든다
- email 을 전부 소문자로 바꿔 저장한다
- GIN 인덱스로 email 을 색인한다
SELECT tenant_id, sum(amount) ... WHERE tenant_id=7 GROUP BY tenant_id 가 힙을 안 만지고 인덱스만 읽게 하려면?
- tenant_id 에 GIN 인덱스를 만든다
- amount 에 BRIN 인덱스를 만든다
- tenant_id 와 amount 를 각각 단일 인덱스로 만든다
- (tenant_id) INCLUDE (amount) 커버링 인덱스를 만든다
jsonb 열에 props @> '{"browser":"safari"}' 같은 담김 질의를 자주 한다. 알맞은 인덱스 종류는?
- GIN 인덱스
- B 트리 인덱스
- BRIN 인덱스
- 해시 인덱스
삽입 순서와 시간이 같은 대용량 시계열 열(occurred_at)에서, B 트리보다 수백 배 작으면서 범위 질의를 받는 인덱스는?
- 부분 인덱스
- 표현식 인덱스
- BRIN 인덱스
- 커버링 인덱스
pg_stat_user_indexes 에서 idx_scan 이 0인 인덱스를 지우는 이유는?
- idx_scan 이 0이면 인덱스가 손상됐다는 뜻이라서
- 아무 질의도 쓰지 않으면서 쓰기마다 갱신 비용과 저장 공간만 무는 부채라서
- 0인 인덱스는 옵티마이저를 느리게 만들어 계획 수립을 지연시켜서
- idx_scan 이 0이면 통계가 수집되지 않아 계획이 틀리기 때문에