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

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

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


== Cardinality (카디널리티) 와 Selectivity (선택도)
== Cardinality (카디널리티) 와 Selectivity (선택도) ==
 
{{핵심
{{핵심
|제목=
|제목= <big>'''핵심: High Cardinality = Low Selectivity = 인덱스 효과적 = 성능 좋음'''</big>
* Cardinality (카디널리티)
* '''Cardinality (카디널리티,고유값 수)'''
** 특정 연산이나 조건에서 반환되는 예상 행의 개수
** 특정 연산이나 조건에서 반환되는 예상 행의 개수
** 절대적인 수치 (행 개수)
** 절대적인 수치 (행 개수)
** 실행 계획의 “Rows” 컬럼에 표시됨
** 실행 계획의 “Rows” 컬럼에 표시됨
*:--------------
::
* Selectivity (선택도)
예시:
** 전체 행 중에서 조건을 만족하는 행의 비율
    성별 컬럼: Cardinality = 2 (남, 여)
    주민번호 컬럼: Cardinality = 1,000,000 (100만 명이면 100만)
 
 
* '''Selectivity (선택도)'''
** 전체 행 중에서 조건을 만족하는 행의 비율 (선택된 row 수 / 전체 row 수)
** 상대적인 비율 (0 ~ 1 사이의 값, 또는 0% ~ 100%)
** 상대적인 비율 (0 ~ 1 사이의 값, 또는 0% ~ 100%)
** 조건의 “선택적” 정도를 나타냄
** 조건의 “선택적” 정도를 나타냄
::
예시:
    성별='남': Selectivity = 0.5 (50%)
    특정 주민번호: Selectivity = 0.000001 (0.0001%)
|내용 =실무에서 사용하는 방식
"이 컬럼 카디널리티가 높아서 인덱스 효과 좋을 거야"
= "이 컬럼 고유값이 많아서 인덱스 효과 좋을 거야"
"성별 컬럼은 카디널리티가 2야"
= "성별 컬럼은 고유값이 2개야"
"카디널리티 체크해봐"= "고유값 개수 확인해봐"
}}
}}


65번째 줄: 83번째 줄:
* Selectivity = 9,000 / 10,000 = 0.9 (90%)
* Selectivity = 9,000 / 10,000 = 0.9 (90%)
* Cardinality = 9,000 (행)
* Cardinality = 9,000 (행)


=== 실행 계획 확인 ==
=== 실행 계획 확인 ==

2026년 1월 23일 (금) 16:11 기준 최신판

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

  vpn_key 핵심: High Cardinality = Low Selectivity = 인덱스 효과적 = 성능 좋음

  • Cardinality (카디널리티,고유값 수)
    • 특정 연산이나 조건에서 반환되는 예상 행의 개수
    • 절대적인 수치 (행 개수)
    • 실행 계획의 “Rows” 컬럼에 표시됨
예시:
    성별 컬럼: Cardinality = 2 (남, 여)
    주민번호 컬럼: Cardinality = 1,000,000 (100만 명이면 100만)


  • Selectivity (선택도)
    • 전체 행 중에서 조건을 만족하는 행의 비율 (선택된 row 수 / 전체 row 수)
    • 상대적인 비율 (0 ~ 1 사이의 값, 또는 0% ~ 100%)
    • 조건의 “선택적” 정도를 나타냄
예시:
    성별='남': Selectivity = 0.5 (50%)
    특정 주민번호: Selectivity = 0.000001 (0.0001%)

  playlist_add_check실무에서 사용하는 방식

"이 컬럼 카디널리티가 높아서 인덱스 효과 좋을 거야" = "이 컬럼 고유값이 많아서 인덱스 효과 좋을 거야"

"성별 컬럼은 카디널리티가 2야" = "성별 컬럼은 고유값이 2개야"

"카디널리티 체크해봐"= "고유값 개수 확인해봐"
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는 조인 순서와 메모리 할당에 영향을 줍니다!​​​​​​​​​​​​​​​​