파티셔닝은 데이터를 더 적게 읽게 만드는 기법이지, 그 자체로 성능을 보장하는 마법이 아니다. 프루닝이 쿼리 조건과 맞물릴 때만 효과가 나고, 파티션 내부에는 여전히 인덱스가 필요하다. 조회 조건이 좁고 고정돼 있으면 파티셔닝보다 부분 인덱스나 복합 인덱스가 더 싸게 먹힐 때가 많다.
파티셔닝을 도입하기 전에 뭘 먼저 확인해야 하나?
쿼리가 파티션 키를 실제로 타는지부터 확인해야 한다. 이걸 건너뛰고 "테이블이 크니까 일단 쪼갠다"는 식으로 접근하면 파티션만 늘어나고 성능은 그대로인 상태가 된다.
- 파티셔닝의 본질은 접근 데이터를 소수 파티션으로 좁히는 것이다.
- 파티션 키가 자주 쓰는 쿼리 조건(WHERE, JOIN 키)과 어긋나면 프루닝이 작동하지 않는다.
enable_partition_pruning같은 설정이 꺼져 있으면 파티션을 나눠도 최적화가 적용되지 않는다.- 읽기 비율이 높아도 조건이 넓으면(테이블 대부분을 훑는 쿼리) 인덱스보다 순차 스캔이 유리할 수 있다.
판교의 로그 적재 테이블이 딱 이런 케이스였다. 일별 3천만 건씩 쌓이는 이벤트 테이블에 created_at B-tree 인덱스만 걸어두고 버티다가, 6개월 지나니 인덱스 크기가 원본 데이터보다 커지고 최근 7일 조회도 200ms를 넘기기 시작했다. 인덱스를 더 늘리는 대신 월 단위 range 파티셔닝으로 갈아탔는데, 이 선택이 맞았는지는 "조회가 정말 최근 파티션에 몰리는가"에 달려 있었다. 실제로 PostgreSQL 문서에 실린 사례에서는 연도별 range 파티셔닝 이후 특정 연도 쿼리가 1.735ms에서 0.207ms로 줄어든 보고가 있는데, 이건 해당 연도 파티션 하나만 스캔하게 되면서 나온 결과지 파티셔닝 자체가 만능이라서가 아니다.
파티션 프루닝은 실제로 어떻게 쿼리를 줄이나?
프루닝은 옵티마이저가 쿼리 실행 전에 조건에 맞지 않는 파티션을 아예 계획에서 빼버리는 과정이다. WHERE created_at >= '2026-01-01' 같은 조건이 파티션 경계와 일치하면, 나머지 11개월치 파티션은 스캔 후보에서 제외된다.
PostgreSQL 공식 문서는 파티셔닝이 "인덱스 상단 트리를 대체"하는 효과가 있다고 설명한다. 큰 테이블 하나에 걸린 인덱스는 루트부터 리프까지 랜덤 I/O가 늘어나지만, 파티션별로 인덱스가 쪼개지면 자주 쓰는 부분(최근 데이터)이 메모리 캐시에 더 잘 맞는다는 논리다. 다만 이 효과는 "접근하는 데이터가 한 파티션이나 소수 파티션에 몰릴 때"라는 전제가 붙는다. 여러 연도를 걸쳐 집계하는 배치 쿼리라면 프루닝 이점이 거의 사라지고, 오히려 파티션 개수만큼 플랜 생성 비용이 늘어날 수 있다.
Azure의 데이터 파티셔닝 가이드도 같은 결을 짚는다. Azure Well-Architected 가이드는 "애플리케이션이 적절한 파티션을 쉽게 고를 수 있는 shard key"를 설계하라고 권고하는데, 이를 못 하면 모든 파티션을 스캔하는 cross-partition 쿼리가 된다고 경고한다. 실무에서는 이게 "파티션 키를 정산일이 아니라 생성일로 잡았더니 정산 조회가 매번 전체 파티션을 훑더라"는 식의 사고로 나타난다.
파티션 안에 인덱스는 왜 또 필요한가?
파티셔닝은 인덱스를 대체하지 않기 때문이다. PostgreSQL 18 문서는 파티션 테이블에도 키 컬럼 인덱스를 두는 것이 대부분의 시나리오에서 도움이 된다고 명시한다. 즉 실무에서는 파티셔닝을 "프루닝으로 후보 파티션을 줄인 뒤, 그 안에서 인덱스로 마지막 탐색을 하는" 2단 구조로 봐야 한다.
이 구조를 놓치면 흔한 함정에 빠진다. 파티션만 나눠놓고 파티션 내부 인덱스를 안 만들면, 프루닝으로 스캔 범위는 줄었어도 그 파티션 안에서는 여전히 순차 스캔이 돈다. 반대로 쿼리나 업데이트가 단일 파티션의 큰 비율을 건드리는 경우(예: 특정 월 전체를 갱신하는 배치)라면 인덱스보다 순차 스캔이 더 나을 수 있다고 PostgreSQL 문서는 못 박는다. 그래서 "파티션 크기를 응답시간 목표 안에 들어오게 줄여라"는 조언이 나온다. 파티션이 너무 크면 프루닝을 해도 그 안에서의 스캔 비용이 SLO를 넘길 수 있다는 뜻이다.
SQL Server 쪽은 여기에 저장 계층 이슈가 하나 더 붙는다. SQL Server 파티션 문서에 따르면 파티션 함수는 파티션 스킴을 통해 여러 filegroup에 매핑된다. 즉 파티셔닝이 논리적 분할뿐 아니라 물리적 저장 위치 분산으로 이어지므로, 오래된 파티션을 저렴한 스토리지로 옮기거나 백업 주기를 다르게 가져가는 아카이빙 전략과도 맞물린다. Oracle의 복합 파티셔닝(range-list, range-hash)도 비슷한 맥락인데, 시간축과 테넌트축처럼 쿼리 패턴이 2차원일 때 한 번 더 쪼개는 구조로 쓰인다.
복합 인덱스와 부분 인덱스는 파티셔닝과 어떻게 역할이 나뉘나?
셋의 역할은 겹치지 않는다. 파티셔닝은 대용량·수명주기·프루닝용, 복합 인덱스는 여러 조건이 동시에 걸리는 쿼리용, 부분 인덱스는 조건이 좁고 안정적인 핫셋용으로 나뉜다.
CMU 15-445 강의 자료는 복합 인덱스가 쿼리가 인덱스의 prefix를 제공할 때 잘 동작한다고 정리한다. (tenant_id, created_at) 인덱스는 "tenant_id로 equality, created_at으로 range"인 쿼리에는 강하지만, created_at만으로 조회하는 쿼리에는 이 인덱스가 거의 도움이 안 된다. 컬럼 순서를 바꾸면 완전히 다른 인덱스가 되는 셈이라, 워크로드가 여러 방향으로 조회를 섞으면 복합 인덱스 하나로는 한계가 뚜렷하다.
부분 인덱스는 반대 방향에서 접근한다. 같은 강의 자료는 활성 데이터나 특정 상태만 자주 조회하는 서비스에 부분 인덱스가 특히 잘 맞는다고 설명한다. 예를 들어 주문 테이블에서 status = 'pending'인 건만 자주 조회한다면, 전체 테이블에 인덱스를 거는 대신 WHERE status = 'pending' 조건이 붙은 부분 인덱스만으로 충분한 경우가 많다. 인덱스 크기가 작아지니 쓰기 시 유지 비용도 줄고, 파티셔닝처럼 테이블 구조를 바꾸는 부담도 없다.
파티셔닝하면 무조건 빨라진다는 말, 맞나?
아니다. 파티션 키가 쿼리 조건과 어긋나면 프루닝이 작동하지 않고, 이 경우 파티셔닝은 오히려 관리 복잡도만 늘리는 결과가 된다. 이게 가장 흔한 오해이자 가장 흔한 실패 모드다.
Azure Cosmos DB 사례가 이 지점을 잘 보여준다. Cosmos DB 파티셔닝 문서는 partition key가 쿼리 패턴과 맞지 않으면 cross-partition query가 발생한다고 설명한다. GSI(전역 보조 인덱스)를 쓰면 이런 문제를 줄일 수 있지만, 추가 스토리지와 RU 비용이 들고 소스 컨테이너와 eventually consistent한 관계가 된다. 강한 일관성이 필요한 워크로드라면 GSI로 읽기를 최적화해도 일관성 요구와 충돌해 비용 대비 이점이 제한될 수 있다.
정규화와 조인도 비슷한 함정이다. Azure Well-Architected 가이드는 기능적 분할과 수평 분할을 결합할 수 있다고 설명하면서도, cross-partition join과 참조 무결성 요구를 줄이라고 강조한다. 정규화가 강하고 조인이 많은 스키마는 파티셔닝의 이점을 상당 부분 깎아먹는다. 읽기 패턴이 명확한 서비스라면 오히려 약간 비정규화된 스키마가 파티셔닝과 궁합이 더 좋을 수 있다는 뜻이다.
언제 파티셔닝을 쓰고 언제 인덱스만으로 충분한가?
읽기 비율이 높고 조회 조건이 파티션 키로 프루닝 가능하면 파티셔닝+파티션 내부 인덱스, 조건이 좁고 고정돼 있으면 부분 인덱스, 다중 컬럼 조건이 반복되면 복합 인덱스가 먼저다. 세 가지를 동시에 검토하고 겹치는 부분은 조합해서 쓰는 게 현실적이다.
적합한 조건은 이렇다. 읽기 비율이 80%지만 조회가 항상 최근 7일·특정 tenant에 몰린다면 range 파티셔닝 + 파티션 내부 복합 인덱스가 맞는다. 반대로 status 값이 하나로 고정된 활성 건만 조회한다면 부분 인덱스가 더 간단하고 싸다. AWS Well-Architected 가이드도 데이터 파티셔닝으로 스캔 시간을 줄이라고 명시하는데, 여기서 핵심은 "더 적게 읽게 만드는 것"이지 무조건 데이터를 나누는 것 자체가 목적이 아니라는 점이다.
피해야 할 조건도 명확하다. 개별 row lookup이 대부분인 워크로드는 파티셔닝보다 좋은 복합 인덱스가 먼저 검토돼야 한다. 배치성으로 테이블 대부분을 훑는 쿼리가 잦다면 파티션을 나눠도 순차 스캔 비용이 그대로 남는다. 그리고 강한 일관성이 필수인 다중 파티션 쓰기는 트랜잭션 경계와 격리 수준이 파티션 설계보다 더 직접적으로 성능과 복잡도를 좌우한다. 파티셔닝을 도입하기 전에 이 셋 중 어디에 해당하는지 먼저 나눠보는 게, 파티션 개수를 정하는 것보다 우선이다.
핵심 정리
- 파티셔닝은 프루닝이 쿼리 조건과 맞물릴 때만 효과가 나며, 파티션 키가 어긋나면 전 파티션 스캔이 된다.
- 파티션은 인덱스를 대체하지 않는다. 프루닝 후 파티션 내부 인덱스로 좁히는 2단 구조로 설계해야 한다.
- 조건이 좁고 고정된 핫셋 조회는 부분 인덱스, 다중 컬럼 equality+range 조합은 복합 인덱스가 더 적합할 수 있다.
- 정규화가 강하고 조인이 많은 스키마, 강한 일관성이 필요한 다중 파티션 쓰기는 파티셔닝 이점을 깎아먹는다.
- 2026년 기준 공통 결론은 "쿼리 패턴이 스키마와 인덱스를 결정한다"는 것이며, 파티션 개수보다 조회 조건 분석이 먼저다.