좋은 질문입니다! 명확하게 정리해드리겠습니다.
- 정답: **인덱스의 Clustering Factor**입니다!
Clustering Factor는 **인덱스의 속성**이지, 테이블의 속성이 아닙니다.
---
- 개념 정리
- 📊 Clustering Factor는 인덱스별로 존재
```sql -- Clustering Factor는 DBA_INDEXES 뷰에 있음 (테이블 뷰가 아님!) SELECT
index_name, -- 인덱스 이름 table_name, -- 참조하는 테이블 clustering_factor -- 이 인덱스의 CF
FROM dba_indexes WHERE table_name = 'EMPLOYEES'; ```
- 결과 예시:**
``` INDEX_NAME TABLE_NAME CLUSTERING_FACTOR
------------ -----------------
EMP_DEPT_IDX EMPLOYEES 1,500 <- 이 인덱스의 CF EMP_NAME_IDX EMPLOYEES 89,000 <- 다른 값! EMP_SALARY_IDX EMPLOYEES 45,000 <- 또 다른 값! ```
---
- 같은 테이블, 다른 인덱스 = 다른 CF
- 실제 예제로 이해하기
```sql -- 테이블 생성 CREATE TABLE employees (
emp_id NUMBER, dept_id NUMBER, hire_date DATE, salary NUMBER
);
-- 데이터 삽입 (dept_id 순서로 정렬되어 입력됨) INSERT INTO employees SELECT LEVEL, MOD(LEVEL, 10) + 1, SYSDATE - LEVEL, LEVEL * 1000 FROM dual CONNECT BY LEVEL <= 100000;
-- 통계 수집 EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'EMPLOYEES');
-- 여러 인덱스 생성 CREATE INDEX emp_dept_idx ON employees(dept_id); CREATE INDEX emp_hire_idx ON employees(hire_date); CREATE INDEX emp_salary_idx ON employees(salary);
-- 각 인덱스의 CF 확인 SELECT
index_name, clustering_factor, num_rows, (SELECT blocks FROM user_tables WHERE table_name = 'EMPLOYEES') AS table_blocks
FROM user_indexes WHERE table_name = 'EMPLOYEES'; ```
- 결과:**
``` INDEX_NAME CLUSTERING_FACTOR NUM_ROWS TABLE_BLOCKS
----------------- -------- ------------
EMP_DEPT_IDX 1,200 100,000 1,200 <- 좋음! ✅ EMP_HIRE_IDX 95,000 100,000 1,200 <- 나쁨! ❌ EMP_SALARY_IDX 98,000 100,000 1,200 <- 나쁨! ❌ ```
- 왜 이런 차이가 발생할까?
- EMP_DEPT_IDX (CF = 1,200) - 좋음**
``` 테이블 물리적 저장 순서: dept_id 순으로 입력됨
Block 1: [dept_id=1, 1, 1, 1, 1...] Block 2: [dept_id=2, 2, 2, 2, 2...] Block 3: [dept_id=3, 3, 3, 3, 3...]
인덱스 스캔: dept_id=1 → 같은 블록 내에서 여러 행 읽기 가능 → Clustering Factor ≈ 블록 수 (1,200) ```
- EMP_HIRE_IDX (CF = 95,000) - 나쁨**
``` 인덱스는 hire_date 순서로 정렬되어 있지만 테이블은 dept_id 순서로 저장됨
인덱스 스캔: hire_date 순으로 읽으면 → 각 행이 서로 다른 블록에 흩어져 있음 → Clustering Factor ≈ 행 수 (95,000) ```
---
- 상세 비교
- DBA_INDEXES vs DBA_TABLES
```sql -- ✅ 있음: 인덱스에는 CLUSTERING_FACTOR 컬럼 존재 DESC dba_indexes; -- CLUSTERING_FACTOR NUMBER
-- ❌ 없음: 테이블에는 CLUSTERING_FACTOR 컬럼 없음 DESC dba_tables; -- CLUSTERING_FACTOR 컬럼 없음! ```
---
- 왜 "인덱스의" 속성인가?
- Clustering Factor의 정의
> **"이 특정 인덱스의 키 순서"와 "테이블 블록의 물리적 배치"가 얼마나 일치하는가**
즉, CF는: - ✅ 인덱스 키 순서와 관련됨 - ✅ 인덱스마다 다름 - ✅ 인덱스 통계의 일부 - ❌ 테이블 자체의 속성이 아님
- 계산 과정 (의사 코드)
```python clustering_factor = 0 previous_block = None
- 이 인덱스를 순서대로 스캔
for row in index.scan_in_key_order():
current_block = row.get_table_block()
if current_block != previous_block:
clustering_factor += 1
previous_block = current_block
- CF는 "인덱스 순서대로 읽을 때" 몇 개의 블록을 접근하는가
```
---
- 실무 예제: 인덱스별 CF 비교
```sql -- 같은 테이블의 모든 인덱스 CF 비교 WITH table_info AS (
SELECT
'EMPLOYEES' AS table_name,
blocks AS table_blocks,
num_rows
FROM user_tables
WHERE table_name = 'EMPLOYEES'
) SELECT
i.index_name,
i.clustering_factor,
t.table_blocks,
t.num_rows,
-- CF 품질 평가
ROUND(i.clustering_factor / t.table_blocks, 2) AS cf_block_ratio,
CASE
WHEN i.clustering_factor <= t.table_blocks * 1.5 THEN '매우 좋음 ⭐⭐⭐'
WHEN i.clustering_factor <= t.table_blocks * 5 THEN '좋음 ⭐⭐'
WHEN i.clustering_factor <= t.num_rows * 0.3 THEN '보통 ⭐'
ELSE '나쁨 ❌'
END AS cf_quality,
-- 이 인덱스로 100행 읽을 때 예상 블록 수
ROUND((i.clustering_factor / t.num_rows) * 100, 0) AS blocks_per_100_rows
FROM user_indexes i CROSS JOIN table_info t WHERE i.table_name = t.table_name ORDER BY i.clustering_factor; ```
- 결과 예시:**
``` INDEX_NAME CF BLOCKS QUALITY BLOCKS_PER_100_ROWS
------ ------ -------------- -------------------
EMP_DEPT_IDX 1,200 1,200 매우 좋음 ⭐⭐⭐ 1 EMP_JOB_IDX 5,000 1,200 좋음 ⭐⭐ 5 EMP_SALARY_IDX 45,000 1,200 보통 ⭐ 45 EMP_NAME_IDX 89,000 1,200 나쁨 ❌ 89 ```
---
- 혼동하기 쉬운 개념 정리
| 개념 | 설명 | 위치 | |-----|------|------| | **Clustering Factor** | 인덱스 키 순서와 테이블 블록 배치의 일치도 | DBA_INDEXES | | **Table Blocks** | 테이블이 차지하는 물리적 블록 수 | DBA_TABLES | | **Index Clustering** | IOT(Index-Organized Table) | 테이블 구조 | | **Hash Cluster** | 여러 테이블을 클러스터 키로 묶음 | DBA_CLUSTERS |
---
- 핵심 정리
```sql -- ✅ 맞는 표현 "EMP_DEPT_IDX 인덱스의 Clustering Factor가 높다" "이 인덱스는 CF가 나쁘다"
-- ❌ 틀린 표현 "EMPLOYEES 테이블의 Clustering Factor가 높다" "테이블 CF가 나쁘다" ```
- 올바른 이해
1. **테이블**: 그냥 블록에 저장되어 있을 뿐 2. **인덱스**: 각각 자신의 키 순서대로 테이블을 가리킴 3. **CF**: 각 인덱스가 테이블을 얼마나 효율적으로 가리키는지 측정
---
- 실전 시나리오
- Q: 테이블을 재구성하면 모든 인덱스의 CF가 좋아지나요?
- A: 아니요! 특정 인덱스 순서로 정렬해야 합니다.**
```sql -- 방법 1: DEPT_ID 인덱스의 CF 개선 CREATE TABLE emp_new AS SELECT * FROM employees ORDER BY dept_id; -- 이 인덱스의 키 순서대로!
-- 결과: -- EMP_DEPT_IDX의 CF: 개선됨 ✅ -- 다른 인덱스들의 CF: 더 나빠질 수 있음 ❌
-- 방법 2: 파티셔닝으로 여러 인덱스 동시 개선 ALTER TABLE employees MODIFY PARTITION BY RANGE (dept_id) ... ```
---
- 결론:** Clustering Factor는 **"이 인덱스로 테이블을 읽을 때의 효율성"**을 나타내는 **인덱스의 통계 정보**입니다. 같은 테이블이라도 인덱스마다 다른 CF 값을 가지며, DBA는 중요한 인덱스의 CF를 모니터링하고 개선해야 합니다!