메뉴 여닫기
개인 메뉴 토글
로그인하지 않음
만약 지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Oracle (토론 | 기여)님의 2025년 10월 2일 (목) 15:53 판 (새 문서: 좋은 질문입니다! 명확하게 정리해드리겠습니다. ## 정답: **인덱스의 Clustering Factor**입니다! Clustering Factor는 **인덱스의 속성**이지, 테이블의 속성이 아닙니다. --- ## 개념 정리 ### 📊 Clustering Factor는 인덱스별로 존재 ```sql -- Clustering Factor는 DBA_INDEXES 뷰에 있음 (테이블 뷰가 아님!) SELECT index_name, -- 인덱스 이름 table_name, -- 참조하는 테이블...)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

좋은 질문입니다! 명확하게 정리해드리겠습니다.

    1. 정답: **인덱스의 Clustering Factor**입니다!

Clustering Factor는 **인덱스의 속성**이지, 테이블의 속성이 아닙니다.

---

    1. 개념 정리
      1. 📊 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 <- 또 다른 값! ```

---

    1. 같은 테이블, 다른 인덱스 = 다른 CF
      1. 실제 예제로 이해하기

```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 <- 나쁨! ❌ ```

      1. 왜 이런 차이가 발생할까?
    • 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) ```

---

    1. 상세 비교
      1. DBA_INDEXES vs DBA_TABLES

```sql -- ✅ 있음: 인덱스에는 CLUSTERING_FACTOR 컬럼 존재 DESC dba_indexes; -- CLUSTERING_FACTOR NUMBER

-- ❌ 없음: 테이블에는 CLUSTERING_FACTOR 컬럼 없음 DESC dba_tables; -- CLUSTERING_FACTOR 컬럼 없음! ```

---

    1. 왜 "인덱스의" 속성인가?
      1. Clustering Factor의 정의

> **"이 특정 인덱스의 키 순서"와 "테이블 블록의 물리적 배치"가 얼마나 일치하는가**

즉, CF는: - ✅ 인덱스 키 순서와 관련됨 - ✅ 인덱스마다 다름 - ✅ 인덱스 통계의 일부 - ❌ 테이블 자체의 속성이 아님

      1. 계산 과정 (의사 코드)

```python clustering_factor = 0 previous_block = None

  1. 이 인덱스를 순서대로 스캔

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
  1. CF는 "인덱스 순서대로 읽을 때" 몇 개의 블록을 접근하는가

```

---

    1. 실무 예제: 인덱스별 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 ```

---

    1. 혼동하기 쉬운 개념 정리

| 개념 | 설명 | 위치 | |-----|------|------| | **Clustering Factor** | 인덱스 키 순서와 테이블 블록 배치의 일치도 | DBA_INDEXES | | **Table Blocks** | 테이블이 차지하는 물리적 블록 수 | DBA_TABLES | | **Index Clustering** | IOT(Index-Organized Table) | 테이블 구조 | | **Hash Cluster** | 여러 테이블을 클러스터 키로 묶음 | DBA_CLUSTERS |

---

    1. 핵심 정리

```sql -- ✅ 맞는 표현 "EMP_DEPT_IDX 인덱스의 Clustering Factor가 높다" "이 인덱스는 CF가 나쁘다"

-- ❌ 틀린 표현 "EMPLOYEES 테이블의 Clustering Factor가 높다" "테이블 CF가 나쁘다" ```

      1. 올바른 이해

1. **테이블**: 그냥 블록에 저장되어 있을 뿐 2. **인덱스**: 각각 자신의 키 순서대로 테이블을 가리킴 3. **CF**: 각 인덱스가 테이블을 얼마나 효율적으로 가리키는지 측정

---

    1. 실전 시나리오
      1. 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를 모니터링하고 개선해야 합니다!