[PostgreSQL] 인덱스가 있는데 안 쓰는 진짜 이유

시리즈 마지막이다. 앞의 두 편에서 행 수 추정을 맞추는 이야기를 했다. 이번엔 추정이 맞아도 인덱스를 안 쓰는 경우다. 인덱스를 만들었는데 EXPLAIN에 여전히 Seq Scan이 나온다. 이때 먼저 가를 것이 있다. 플래너가 인덱스를 못 쓰는 건지, 안 쓰는 건지. 못 쓰는 경우 조건의 모양이 인덱스와 안 맞으면 플래너는 선택지 자체가 없다. 컬럼에 함수를 씌웠다. WHERE lower(email) = 'a@b.com' -- email 인덱스 못 씀 WHERE date(created_at) = '2026-09-01' -- created_at 인덱스 못 씀 WHERE created_at + interval '1 day' > now() 인덱스는 email의 값으로 정렬돼 있지 lower(email)의 값으로 정렬돼 있지 않다. 표현식 인덱스를 만들거나, 조건을 컬럼이 그대로 남는 형태로 바꾼다. ...

9월 21, 2026 · Jun Kang

[PostgreSQL] HOT update와 fillfactor — 죽은 튜플을 덜 만드는 쪽

앞선 세 편은 이미 생긴 죽은 튜플을 어떻게 치울 것인가에 대한 이야기였다. 이번 편은 반대쪽이다. 애초에 덜 만드는 방법. UPDATE가 인덱스까지 건드리는 문제 PostgreSQL에서 UPDATE는 새 버전을 쓰는 일이라고 1편에서 정리했다. 그런데 여기 딸려오는 비용이 하나 더 있다. 새 버전이 생기면 그 위치를 가리키도록 인덱스도 갱신해야 한다. 인덱스가 다섯 개인 테이블에서 한 행을 UPDATE하면, 힙에 새 버전 하나가 생기고 인덱스 다섯 곳에 엔트리가 추가된다. 그래서 갱신이 잦은 테이블은 힙보다 인덱스가 먼저 부푸는 경우가 많다. 그리고 인덱스 팽창은 조회 성능에 직접 영향을 준다. ...

9월 12, 2026 · Jun Kang

[PostgreSQL] 미사용 인덱스(INDEX) 찾기 및 삭제, 성능향상

1. 인덱스(INDEX) 상세 개념 Postgresql 인덱스(INDEX)개념 및 생성, 삭제, 분석, 설계 방법 2. 미사용 인덱스 간단히 말해, 인덱스는 지정 컬럼에 매핑된 정보를 별도로 저장하고 있다. 보통 플랜 확인을 통해 효율적으로 인덱스를 추가하여 쿼리 최적화를 진행하게 된다. 오래되고 변경이 잦은 어플리케이션일수록 미사용 인덱스는 늘어나고, 인덱스가 사용되지 않는 경우를 매번 모니터링하여 삭제하는 것은 힘든 일이다. 하지만 불필요 인덱스는 디비 성능저하 및 vacuum 코스트를 증가시키기에, 최적화된 인덱스 생성만큼 최적화된 인덱스 삭제도 중요하다. ...

10월 6, 2023 · Jun Kang

[PostgreSQL] 인덱스(INDEX)개념 및 생성, 삭제, 분석, 설계 방법

1. 인덱스 컨트롤 1-1. 인덱스 조회 SELECT * FROM pg_indexes WHERE tablename = '{테이블명}'; -- 테이블명에 '' 필요 1-2. 인덱스 생성 -- 단일 인덱스 CREATE INDEX {인덱스명} ON {테이블명} USING btree({컬럼명}); -- 결합 인덱스 CREATE INDEX {인덱스명} ON {테이블명} USING btree({컬럼명1}, {컬럼명2}); -- 유니크 인덱스 CREATE UNIQUE INDEX {인덱스명} ON table_name ({컬럼명}); 1-3. 인덱스 삭제 DROP INDEX {인덱스명}; 1-4. 인덱스 사용 빈도 확인 SELECT schemaname, relname, indexrelname, idx_scan as idx_scan_cnt FROM pg_stat_user_indexes ORDER BY idx_scan; 1-5. 인덱스 손상 시 재인덱싱 REINDEX INDEX {인덱스명} REINDEX TABLE {테이블명} REINDEX DATABASE {데이터베이스명} ...

9월 12, 2023 · Jun Kang