메뉴 여닫기
개인 메뉴 토글
로그인하지 않음
만약 지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Dbstudy (토론 | 기여)님의 2026년 10월 1일 (목) 18:18 판
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

힙테이블(heap table)

 list_altHEAP의 뜻
  • 영어 "heap"은 **"(물건을 아무렇게나) 쌓아 놓은 더미"**라는 뜻입니다. 자료구조의 힙(우선순위 큐)과는 관계가 없습니다.
  • 행을 정렬 순서 없이 빈자리가 있는 곳에 그냥 쌓아 둔다는 의미에서 붙은 이름입니다.

동작 원리

1. 저장 (INSERT)

새 행은 키 순서와 상관없이 빈 공간이 있는 블록(페이지)에 들어갑니다. 빈 공간이 어디 있는지는 별도 구조로 관리합니다.

oracle vs sql server
구분 Oracle SQL Server
빈 공간 관리 ASSM 비트맵 블록 (예전엔 Freelist) PFS(Page Free Space) 페이지
세그먼트 헤더, Extent Map IAM(Index Allocation Map) 페이지
HWM (High Water Mark) | 별도 HWM 없음, IAM에 할당된 범위

2. row(행) 의 주소

행은 물리 위치로 식별됩니다. Oracle은 **ROWID**(오브젝트·파일·블록·슬롯), SQL Server는 **RID**(파일:페이지:슬롯)를 씁니다. 보조 인덱스의 리프에는 키 값과 이 주소가 저장됩니다.

3. 조회

- * 조건 없이 읽을 때: 테이블에 속한 블록을 처음부터 끝까지 모두 읽습니다.

Oracle은 HWM까지 읽는 Full Table Scan, SQL Server는 IAM 순서대로 읽는 Table Scan

- * 인덱스로 찾을 때: 인덱스에서 ROWID/RID를 얻은 뒤 해당 블록을 바로 읽습니다.

Oracle은 TABLE ACCESS BY INDEX ROWID, SQL Server는 RID Lookup

4. 수정 (UPDATE)으로 행이 커질 때

행이 블록에 더 이상 들어가지 않으면 다른 블록으로 옮겨집니다.
이때 원래 자리에는 새 위치를 가리키는 포인터만 남깁니다. 인덱스에 저장된 ROWID/RID를 고치지 않아도 되게 하려는 장치입니다.
- Oracle: Row Migration
- SQL Server: Forwarded Record
  • 장점
- INSERT가 빠릅니다. 정렬 위치를 찾을 필요 없이 빈 공간이나 끝에 붙이면 됩니다. 페이지 분할(Page Split)이 없습니다.
- 대량 적재에 유리합니다. SQL Server의 BULK INSERT, Oracle의 Direct-path INSERT(APPEND)처럼 최소 로깅으로 빠르게 적재할 수 있습니다.
- 인덱스로 단건을 찾는 비용이 낮습니다. ROWID/RID가 물리 주소라서 블록을 한 번에 찾아갑니다. 반대로 클러스터드 테이블은 보조 인덱스에서 클러스터링 키를 얻은 뒤 클러스터드 B-tree를 한 번 더 탐색해야 합니다(Key Lookup).
- 구조가 단순합니다. 키 순서를 유지하는 비용이 없어서 스테이징·임시·로그 테이블에 적합합니다.
  • 단점
- 범위 조회가 느립니다. 같은 범위의 데이터가 여러 블록에 흩어져 있어서, 범위로 많이 읽으면 랜덤 I/O가 많아집니다.
Oracle에서 말하는 Clustering Factor가 나쁜 상태입니다.
- 행 이동으로 I/O가 늘어납니다. Row Migration이나 Forwarded Record가 쌓이면 행 하나를 읽는 데 블록을 두 번 읽습니다.
- 삭제해도 공간이 줄지 않습니다.
- Oracle: DELETE 후에도 HWM이 내려가지 않아 Full Scan이 빈 블록까지 읽습니다.
- SQL Server: DELETE 후 빈 페이지가 해제되지 않는 경우가 많습니다.
- 정리하려면 Oracle은 `ALTER TABLE MOVE` 또는 `SHRINK SPACE`, SQL Server는 `ALTER TABLE ... REBUILD`가 필요합니다.
- SQL Server에서는 관리 도구가 약합니다. 인덱스 REBUILD나 REORGANIZE 같은 일상 유지보수의 대상이 되지 않습니다. 그래서 방치되기 쉽습니다.

언제 쓰는가

힙이 적합 클러스터드(IOT)가 적합
대량 적재 후 통째로 읽는 스테이징·ETL 테이블 키로 범위 조회가 많은 테이블 (일자별 조회 등)
쓰고 거의 읽지 않는 로그 행 크기가 자주 변하는 UPDATE 위주 테이블
작은 코드성 테이블 대용량 이력 테이블 (일자 또는 IDENTITY 키)


menu_book * 실제 예시)

- wwUserPreferenceLog(5,300만 건): 쓰기만 하고 거의 안 읽는다면 힙도 괜찮습니다.

일자별 조회나 정리 작업을 한다면 일자 기준 클러스터드 인덱스가 낫습니다.

- HWorkDaily: 이름상 일자별 조회가 잦을 테이블이라 클러스터드 인덱스가 적합합니다.

  • 어느 쪽이든 실제 판단은 forwarded_record_count, 빈 공간 비율, 조회 패턴을 확인한 뒤에 하는 게 맞습니다.