메뉴 여닫기
개인 메뉴 토글
로그인하지 않음
만약 지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

카디널리티 와 셀렉티비티: 두 판 사이의 차이

DB스터디
(새 문서: == Cardinality (카디널리티) 와 Selectivity (선택도) {{핵심 |제목= * Cardinality (카디널리티) ** 특정 연산이나 조건에서 반환되는 예상 행의 개수 ** 절대적인 수치 (행 개수) ** 실행 계획의 “Rows” 컬럼에 표시됨 *:-------------- * Selectivity (선택도) ** 전체 행 중에서 조건을 만족하는 행의 비율 ** 상대적인 비율 (0 ~ 1 사이의 값, 또는 0% ~ 100%) ** 조건의 “선택적” 정도를 나타...)
 
편집 요약 없음
 
1번째 줄: 1번째 줄:


== Cardinality (카디널리티) 와 Selectivity (선택도)
== Cardinality (카디널리티) 와 Selectivity (선택도) ==
 
{{핵심
{{핵심
|제목=
|제목=

2025년 10월 24일 (금) 13:01 기준 최신판

Cardinality (카디널리티) 와 Selectivity (선택도)

  vpn_key * Cardinality (카디널리티)

    • 특정 연산이나 조건에서 반환되는 예상 행의 개수
    • 절대적인 수치 (행 개수)
    • 실행 계획의 “Rows” 컬럼에 표시됨
    --------------
  • Selectivity (선택도)
    • 전체 행 중에서 조건을 만족하는 행의 비율
    • 상대적인 비율 (0 ~ 1 사이의 값, 또는 0% ~ 100%)
    • 조건의 “선택적” 정도를 나타냄
  playlist_add_check
Cardinality = Total Rows × Selectivity

Selectivity = Cardinality / Total Rows

실무 예제

  • 예제 1: 단순 테이블
-- 직원 테이블
CREATE TABLE employees (
    emp_id NUMBER,
    dept_id NUMBER,
    salary NUMBER,
    status VARCHAR2(20)
);

-- 통계 정보
-- Total Rows: 10,000명
-- dept_id = 10: 500명
-- salary > 5000: 3,000명
-- status = 'ACTIVE': 9,000명


-- Query 1

SELECT * FROM employees WHERE dept_id = 10;
  • Selectivity = 500 / 10,000 = 0.05 (5%)
  • Cardinality = 500 (행)

-- Query 2

SELECT * FROM employees WHERE salary > 5000;
  • Selectivity = 3,000 / 10,000 = 0.3 (30%)
  • Cardinality = 3,000 (행)

-- Query 3

SELECT * FROM employees WHERE status = 'ACTIVE';
  • Selectivity = 9,000 / 10,000 = 0.9 (90%)
  • Cardinality = 9,000 (행)


= 실행 계획 확인

-- 통계 수집
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'EMPLOYEES');

-- 실행 계획 확인
EXPLAIN PLAN FOR
SELECT * FROM employees WHERE dept_id = 10;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);


  • 실행 계획 결과:
-------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |   500 |  5000 |    10   (0)|
|*  1 |  TABLE ACCESS FULL| EMPLOYEES |   500 |  5000 |    10   (0)|
-------------------------------------------------------------------------

Predicate Information:
   1 - filter("DEPT_ID"=10)

Rows = 500  ← 이것이 Cardinality


Selectivity 계산 공식

1. 등호(=) 조건

-- WHERE column = value

Selectivity = 1 / NUM_DISTINCT

예: dept_id의 distinct 값이 20개
Selectivity = 1 / 20 = 0.05

2. 범위 조건

-- WHERE column > value

Selectivity = (MAX_VALUE - value) / (MAX_VALUE - MIN_VALUE)

예: salary BETWEEN 3000 AND 10000
    조건: salary > 5000
Selectivity = (10000 - 5000) / (10000 - 3000) = 5000/7000 ≈ 0.71


3. NULL 조건

-- WHERE column IS NULL

Selectivity = NUM_NULLS / NUM_ROWS

예: 10,000행 중 500개가 NULL
Selectivity = 500 / 10,000 = 0.05

4. 복합 조건 (AND)

-- WHERE col1 = 10 AND col2 = 'A'

Selectivity = Selectivity(col1) × Selectivity(col2)

예:
Selectivity(col1) = 0.05
Selectivity(col2) = 0.1
Total Selectivity = 0.05 × 0.1 = 0.005 (0.5%)
Cardinality = 10,000 × 0.005 = 50

5. 복합 조건 (OR)

-- WHERE col1 = 10 OR col2 = 'A'

Selectivity = Sel(col1) + Sel(col2) - (Sel(col1) × Sel(col2))

예:
Selectivity(col1) = 0.05
Selectivity(col2) = 0.1
Total Selectivity = 0.05 + 0.1 - (0.05 × 0.1) = 0.145
Cardinality = 10,000 × 0.145 = 1,450


통계 정보에서 확인

-- Selectivity 관련 통계
SELECT table_name, 
       column_name,
       num_distinct,     -- distinct 값 개수
       num_nulls,        -- NULL 개수
       density,          -- 1/num_distinct (Selectivity)
       num_rows          -- 전체 행 수
FROM user_tab_col_statistics
WHERE table_name = 'EMPLOYEES';


  • 결과 예시:
COLUMN_NAME  NUM_DISTINCT  NUM_NULLS  DENSITY   NUM_ROWS
---------------------------------------------------------
EMP_ID       10000         0          0.0001    10000
DEPT_ID      20            0          0.05      10000  ← Selectivity
SALARY       500           100        0.002     10000
STATUS       2             0          0.5       10000


실무에서의 중요성

1. 인덱스 생성 판단

-- Selectivity가 낮을수록 (선택적일수록) 인덱스 효과 좋음

-- 좋은 경우 (Selectivity: 0.001%)
CREATE INDEX idx_emp_id ON employees(emp_id);
-- emp_id는 고유값, 조회 시 1-2건만 반환

-- 나쁜 경우 (Selectivity: 90%)
CREATE INDEX idx_status ON employees(status);
-- status는 ACTIVE/INACTIVE 2개 값, 조회 시 9000건 반환
-- Full Table Scan이 더 효율적

2. 조인 순서 결정

-- Cardinality가 작은 테이블을 먼저 처리

SELECT /*+ LEADING(d e) */ *
FROM departments d
JOIN employees e ON d.dept_id = e.dept_id
WHERE d.location = 'SEOUL';

-- d 테이블의 Cardinality: 10 (Selectivity 1%)
-- e 테이블의 Cardinality: 10000 (Selectivity 100%)
-- → departments를 먼저 필터링하는 것이 효율적

3. 통계 정확도 확인

-- 실제 Cardinality vs 예상 Cardinality
SELECT /*+ GATHER_PLAN_STATISTICS */ *
FROM employees
WHERE dept_id = 10;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'ALLSTATS LAST'));


  • 결과:
-------------------------------------------------------------------
| Id | Operation         | Name | Starts | E-Rows | A-Rows | ...
-------------------------------------------------------------------
|  0 | SELECT STATEMENT  |      |      1 |        |    520 | ...
|* 1 | TABLE ACCESS FULL | EMP  |      1 |    500 |    520 | ...
-------------------------------------------------------------------

E-Rows: 500  ← 예상 Cardinality (Estimated)
A-Rows: 520  ← 실제 Cardinality (Actual)
차이: 4% (통계가 정확함)


핵심 차이점 요약

|구분 |Cardinality |Selectivity| |-------|--------------|-----------| |**의미** |반환되는 행의 개수 |선택되는 행의 비율 | |**단위** |행 (rows) |비율 (0~1) | |**타입** |절대값 |상대값 | |**사용처**|실행 계획, Cost 계산|조건 효율성 판단 | |**예시** |500 rows |5% (0.05) |

    • 실무 팁:** Selectivity가 5% 이하일 때 인덱스 사용이 효과적이고, Cardinality는 조인 순서와 메모리 할당에 영향을 줍니다!​​​​​​​​​​​​​​​​