옵티마이저 통계의 기초: Table·Column Statistics 읽기
NUM_ROWS·BLOCKS와 NDV·NULL·Low/High·Histogram이 기본 Cardinality와 값별 Selectivity 추정에 미치는 영향을 이해합니다.
핵심 요약
Oracle Optimizer는 SQL을 실행하기 전에 모든 Data를 직접 읽을 수 없으므로 Data Dictionary의 Optimizer Statistics로 각 후보 Plan의 Selectivity·Cardinality·Cost를 추정합니다.
Table·Column·Index·System Statistics
+ Extended·Dynamic Statistics
→ Predicate Selectivity
→ Row Source Cardinality
→ Access Path·Join Order·Join Method·Sort 비용
→ 최저 Cost Plan 선택
Optimizer Statistics는 실시간 계측값이 아니라 수집·유지 시점의 Data를 요약한 값입니다.
Optimizer Statistics
→ 실행 전 예상
→ E-Rows·Cost의 근거
Runtime Statistics
→ 특정 Cursor 실행의 실제 작업량
→ Starts·A-Rows·Buffers·Reads·A-Time
통계 진단의 핵심은 숫자를 단독으로 보는 것이 아니라 다음 흐름을 연결하는 것입니다.
통계 값·수집 범위·시점
→ Optimizer 예상 E-Rows
→ 선택된 Access Path·Join
→ 실제 A-Rows·Buffers
→ 최초 추정 오차 원인
이 이론의 범위
이 이론은 SQLP의
SQL 고급활용 및 튜닝 → 옵티마이저와 통계정보 → Table·Column Statistics범위에서 기본 통계의 의미와 실행계획 추정 오류 진단을 다룹니다.
학습 목표
이 이론을 학습한 뒤에는 다음을 설명할 수 있어야 합니다.
- Optimizer Statistics와 Runtime Statistics를 구분한다.
NUM_ROWS,BLOCKS,AVG_ROW_LEN,SAMPLE_SIZE를 해석한다.NUM_DISTINCT,NUM_NULLS,LOW_VALUE,HIGH_VALUE,DENSITY를 해석한다.- Histogram이 없는 등치 Predicate의 단순 Selectivity·Cardinality 모델을 설명한다.
- Non-NULL 평균 빈도와 Optimizer의 단순 공식을 구분한다.
- Histogram 유형과
DENSITY의 한계를 설명한다. LAST_ANALYZED,STALE_STATS,STALE_PERCENT를 함께 해석한다.- Global·Partition Statistics와 Incremental Statistics의 관계를 설명한다.
- Extended Statistics와 Dynamic Statistics가 필요한 조건을 설명한다.
- Starts가 있는 Row Source에서 E-Rows·A-Rows 비교 단위를 맞춘다.
- 최초 Cardinality 오차 지점에서 필요한 통계만 선택해 보완한다.
1. Optimizer Statistics의 역할
Optimizer의 Estimator는 Data Dictionary Statistics를 사용해 다음을 예상합니다.
Selectivity
→ Predicate가 전체 Row 중 선택할 비율
Cardinality
→ 각 Plan Operation이 반환할 예상 Row 수
Cost
→ 예상 I/O·CPU·Memory 사용량의 내부 비교값
Cardinality는 Access Path·Join Order·Join Method·Sort Memory에 연쇄적으로 영향을 줍니다.
Driving Row 과대 추정
→ Hash Join·Full Scan 쪽 비용이 상대적으로 유리해질 수 있음
Driving Row 과소 추정
→ Nested Loops Inner Probe가 실제로 과도하게 반복될 수 있음
Cost는 실행 초 단위가 아니며 동일 SQL·동일 Optimizer 환경의 후보 Plan을 비교하는 내부 숫자입니다.
2. Statistics 종류
| 종류 | 대표 정보 | 주요 용도 |
|---|---|---|
| Table Statistics | Row·Block·평균 Row 길이 | Full Scan·Join 입력 크기 |
| Column Statistics | NDV·NULL·Low/High·Histogram | Predicate Selectivity·Cardinality |
| Index Statistics | BLEVEL·Leaf Blocks·Clustering | Index Scan·ROWID Access Cost |
| System Statistics | CPU·Single/Multiblock I/O | I/O·CPU 작업의 공통 Cost 비교 |
| Extended Statistics | Column Group·Expression | 상관 Column·표현식 Predicate |
| Dynamic Statistics | Parse 중 Block Sample | 통계 Missing·Stale·Insufficient 보완 |
| Runtime Statistics | Starts·A-Rows·Buffers 등 | 실행 후 예상 오차·실제 병목 확인 |
이 이론은 Table·Column Statistics를 중심으로 하며, 다른 종류는 원인을 분류하는 수준에서 연결합니다.
3. Optimizer Statistics와 Runtime Statistics
| 구분 | Optimizer Statistics | Runtime Statistics |
|---|---|---|
| 시점 | Parse·Optimization 전 사용 | SQL 실행 중·후 측정 |
| 목적 | 예상 Plan 선택 | 실제 작업량 검증 |
| 대표 View | USER_TAB_STATISTICS, USER_TAB_COL_STATISTICS | V$SQL_PLAN_STATISTICS_ALL, Cursor |
| 대표 값 | NUM_ROWS, NDV, Histogram | Starts, A-Rows, Buffers, Reads |
| Plan 표시 | E-Rows, Cost | ALLSTATS LAST의 A-Rows 등 |
| 범위 | Object의 수집 시점 요약 | 특정 SQL_ID·Child Cursor·실행 |
NUM_ROWS=1,000,000
≠ 지금 이 순간 COUNT(*)=1,000,000이라는 보장
A-Rows=15,000
= 해당 Cursor 실행에서 Row Source가 상위로 반환한 실제 Row
4. Table Statistics
4.1 주요 항목
| 항목 | 의미 | 해석 |
|---|---|---|
NUM_ROWS | Object Statistics의 Row 수 | Cardinality·Join 입력의 기준 |
BLOCKS | Statistics에 기록된 사용 Data Block 수 | Full Scan Cost의 핵심 입력 |
AVG_ROW_LEN | Row Overhead를 포함한 평균 Row 길이 | Bytes·Memory·I/O 예상 |
SAMPLE_SIZE | 통계 수집에 사용된 Sample Row 수 | 수집 근거와 규모 확인 |
LAST_ANALYZED | 최근 Statistics 수집 시각 | 현재 Data와 시점 차이 확인 |
STALE_STATS | 변경량 기준 Stale 여부 | 자동·수동 재수집 후보 |
GLOBAL_STATS | Gather·Incremental 유지 여부 | Partition·Global 범위 해석 |
USER_STATS | 사용자가 Statistics를 직접 설정했는지 | 인위적 통계 여부 확인 |
NOTES | Online·Incremental 등 추가 속성 | Statistics 생성 경로 확인 |
SELECT table_name,
partition_name,
object_type,
num_rows,
blocks,
avg_row_len,
sample_size,
last_analyzed,
stale_stats,
global_stats,
user_stats,
notes
FROM user_tab_statistics
WHERE table_name = 'ORDERS'
ORDER BY object_type, partition_name;
4.2 BLOCKS와 Segment 할당량
USER_TAB_STATISTICS.BLOCKS는 Optimizer Statistics의 Used Block 수입니다. Segment에 할당된 전체 Block·Byte는 별도 View에서 확인합니다.
SELECT segment_name,
segment_type,
blocks,
bytes
FROM user_segments
WHERE segment_name = 'ORDERS';
Table Statistics BLOCKS
→ Cost 계산용 Object 통계
Segment BLOCKS
→ 현재 할당된 물리 공간
High Water Mark Scan 범위
→ 실제 Full Scan·Segment 상태와 연결해 별도 확인
같은 이름의 Column을 혼합하지 않습니다.
5. Statistics 수집 Sample
DBMS_STATS.GATHER_TABLE_STATS의 ESTIMATE_PERCENT는 Sample 비율을 제어합니다. 기본 방향은 DBMS_STATS.AUTO_SAMPLE_SIZE로 Oracle이 적절한 Sample을 선택하게 하는 것입니다.
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => USER,
tabname => 'ORDERS',
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
method_opt => 'FOR ALL COLUMNS SIZE AUTO',
cascade => DBMS_STATS.AUTO_CASCADE
);
END;
/
확인할 사항입니다.
SAMPLE_SIZE가 작다고 Statistics가 반드시 나쁜 것은 아님- 100% Sample이 모든 상관관계·표현식 문제를 자동 해결하지 않음
- Column Group·Expression Statistics가 없으면 Data 관계를 표현하지 못할 수 있음
- Partitioned Table은
GRANULARITY, Incremental 설정과 Global Statistics를 함께 확인 CASCADE는 Index Statistics 수집 여부와 연결됨
Sample 정확도
+ 필요한 Statistics 종류
+ Data 분포·상관관계 표현
→ 전체 통계 품질
6. Column Statistics
6.1 주요 항목
| 항목 | 의미 | 주의 |
|---|---|---|
NUM_DISTINCT | Non-NULL Distinct Value 수, NDV | NULL은 별도 관리 |
NUM_NULLS | NULL Row 수 | Equality 결과에는 일반적으로 포함되지 않음 |
LOW_VALUE | 통계상 최솟값 | RAW 내부 형식 |
HIGH_VALUE | 통계상 최댓값 | 증가형 Column의 최신 범위 확인 |
DENSITY | 값 Selectivity 계산에 쓰이는 밀도 | Histogram 유무에 따라 의미가 달라짐 |
AVG_COL_LEN | 평균 Column Byte 길이 | Row·Projection Bytes 예상 |
HISTOGRAM | Histogram 유형 | 편중 표현 방식 |
NUM_BUCKETS | Histogram Bucket 수 | Histogram 유형과 함께 해석 |
SAMPLE_SIZE | Column Statistics Sample Row 수 | Table Sample과 비교 |
LAST_ANALYZED | Column 최근 분석 시각 | Table Statistics 시점과 비교 |
SELECT column_name,
num_distinct,
num_nulls,
low_value,
high_value,
density,
avg_col_len,
histogram,
num_buckets,
sample_size,
last_analyzed,
global_stats,
notes
FROM user_tab_col_statistics
WHERE table_name = 'ORDERS'
ORDER BY column_name;
6.2 Histogram 유형
Oracle 26ai Data Dictionary가 표시할 수 있는 대표 유형입니다.
NONE
FREQUENCY
TOP-FREQUENCY
HYBRID
HEIGHT BALANCED
Histogram은 별도 이론에서 자세히 다루지만 기본 원칙은 다음과 같습니다.
Histogram 없음
→ 균등 분포 가정의 영향이 큼
Histogram 있음
→ 인기값·비인기값·Bucket 정보로 값별 추정 보완
7. 단순 등치 조건 추정
7.1 Oracle의 가장 단순한 공식
단일 Table·단일 Equality Predicate·Histogram 없음이라는 단순 조건에서 Oracle 문서는 다음 모델을 설명합니다.
Selectivity ≈ 1 / NDV
Cardinality ≈ NUM_ROWS / NDV
예시입니다.
NUM_ROWS = 1,000,000
NDV = 4
개념적 Cardinality ≈ 250,000
실제 Optimizer에는 NULL·Density·Bind·Data Type·Histogram·Internal 보정이 추가될 수 있습니다.
7.2 Non-NULL 평균 빈도
Data 자체의 평균 빈도를 이해할 때는 다음 계산도 유용합니다.
Non-NULL Row = NUM_ROWS - NUM_NULLS
Average Non-NULL Frequency
= (NUM_ROWS - NUM_NULLS) / NDV
예시입니다.
NUM_ROWS = 1,000,000
NUM_NULLS = 100,000
NDV = 4
Non-NULL 평균 빈도 = 900,000 / 4 = 225,000
두 계산을 혼동하지 않습니다.
NUM_ROWS / NDV
→ Oracle 문서의 가장 단순한 Cardinality 설명
(ROWS - NULLS) / NDV
→ Data의 Non-NULL 값당 평균 빈도 이해
실제 E-Rows
→ Density·Histogram·Predicate·Optimizer 계산 결과
8. DENSITY를 해석하는 방법
Oracle Data Dictionary의 공식 설명입니다.
Histogram 없음
DENSITY = 1 / NUM_DISTINCT
Histogram 있음
DENSITY는 Histogram Endpoint 관계를 반영
모든 값의 Selectivity를 단일 DENSITY로 설명할 수 없음
따라서 다음 판단은 위험합니다.
DENSITY 하나
→ 모든 Popular·Nonpopular 값 Cardinality를 동일하게 계산
값 편중이 있는 경우 Histogram Bucket·Endpoint와 실제 Bind 값을 함께 봅니다.
9. NULL Statistics와 Predicate
9.1 Equality
WHERE status = 'READY'
NULL은 Equality TRUE가 아니므로 일반 결과에 포함되지 않습니다.
9.2 IS NULL
WHERE status IS NULL
NUM_NULLS가 직접 관련된 Predicate입니다.
9.3 NOT IN
NULL 포함 여부는 3값 논리 때문에 결과 의미를 크게 바꿀 수 있으며 단순 NDV 추정 문제와 구분합니다.
9.4 Join
Nullable Join Column은 NULL Row가 Equality Join에 매칭되지 않는다는 점을 Cardinality에서 고려해야 합니다.
10. LOW_VALUE·HIGH_VALUE
LOW_VALUE와 HIGH_VALUE는 Column의 통계상 최솟값·최댓값이며 RAW로 저장됩니다.
중요한 상황입니다.
- 날짜·Sequence가 계속 증가
- Statistics 이후 최신 값이
HIGH_VALUE밖으로 증가 - 과거 Data 삭제 후 실제 범위가 축소
- Range Predicate가 통계 범위 밖을 조회
- Partition별 Low·High와 Global 범위가 다름
Statistics HIGH_VALUE = 2026-07-01
실제 Data Max = 2026-08-01
Predicate = 2026-07-31 이상
→ 최신 구간 빈도·Cardinality를 부정확하게 추정할 수 있음
LOW_VALUE·HIGH_VALUE는 전체 분포를 보여 주는 Histogram이 아니며 단순 문자열 변환 결과만으로 분포를 단정하지 않습니다.
11. STALE_STATS와 STALE_PERCENT
Oracle은 Table Monitoring의 근사 DML 변경량과 DBMS_STATS의 STALE_PERCENT Preference를 사용해 Stale 여부를 판단합니다.
STALE_STATS = YES
→ 변경량 기준으로 Statistics가 Stale
STALE_STATS = NO
→ Stale 임계치를 넘지 않음
STALE_STATS = NULL
→ Statistics가 수집되지 않은 상태 가능
SELECT DBMS_STATS.GET_PREFS(
pname => 'STALE_PERCENT',
ownname => USER,
tabname => 'ORDERS'
) AS stale_percent
FROM dual;
STALE_STATS='NO'가 보장하지 않는 것:
- 특정 인기값에 변경이 집중되지 않았음
- Column 상관관계가 정확함
- Expression Statistics가 충분함
- 최신 증가형 값이 HIGH_VALUE 안에 있음
- 특정 Partition과 Global Statistics가 모두 적절함
- 모든 Bind의 Cardinality가 정확함
11.1 오래돼도 영향이 작은 경우
- 거의 변하지 않는 Code Table
- 항상 PK 단건 조회
- Data 변화가 Plan 선택에 민감하지 않음
11.2 짧은 시간에도 문제인 경우
- 대량 Load·Partition Exchange 직후
- 특정 Status·Tenant에 Data가 집중
- 최신 날짜만 급증
- Column 관계가 업무 변화로 변경
- Statistics 없는 신규 Partition
12. Global·Partition Statistics
Partitioned Table은 다음 수준의 Statistics를 가질 수 있습니다.
Global Table Statistics
Partition Statistics
Subpartition Statistics
Global·Partition Column Statistics
Query가 Partition Pruning으로 한 Partition만 읽는다면 대상 Partition Statistics가 중요합니다. 여러 Partition을 조회하면 Global Statistics와 Partition Statistics의 일관성을 확인합니다.
Incremental Statistics는 Partition Synopsis를 이용해 Global Statistics 유지 비용을 줄이는 데 도움을 줄 수 있습니다.
확인합니다.
PARTITION_NAME,OBJECT_TYPEGLOBAL_STATS,NOTES- Partition
NUM_ROWS·BLOCKS - Global·Partition
LAST_ANALYZED - 신규·교환 Partition의 통계
- Pruning된 Plan의 PSTART·PSTOP
13. Extended·Dynamic Statistics
13.1 Column Group Statistics
WHERE region_code = :region
AND store_code = :store
두 Column이 강하게 상관되면 개별 NDV를 독립적으로 곱하는 추정이 크게 틀릴 수 있습니다.
Column Group Statistics
→ 같은 Table의 여러 Column 관계를 표현
13.2 Expression Statistics
WHERE UPPER(customer_name) = :name
Base Column Statistics만으로 Expression 결과 분포를 알기 어렵습니다.
Expression Statistics
→ 함수·계산식 결과의 Selectivity 추정 보완
13.3 Dynamic Statistics
Optimizer Statistics가 Missing·Stale·Insufficient하거나 Parallel Query 등의 조건에서 Parse 중 Table Block Sample을 읽어 보조 추정을 만들 수 있습니다.
장점
→ 부족한 Statistics를 Parse 시점에 일부 보완
비용
→ Recursive SQL·Hard Parse Overhead
→ 영구 Statistics를 완전히 대체하지 않음
14. 실행계획에서 추정 오류 찾기
SELECT /*+ GATHER_PLAN_STATISTICS */
order_id,
customer_id,
amount
FROM orders
WHERE status = 'ERROR';
SELECT *
FROM TABLE(
DBMS_XPLAN.DISPLAY_CURSOR(
:sql_id,
:child_no,
'ALLSTATS LAST +PREDICATE +ALIAS +NOTE'
)
);
예시입니다.
| Id | Operation | Starts | E-Rows | A-Rows | Buffers |
|---:|--------------------|-------:|-------:|-------:|--------:|
| 1 | TABLE ACCESS FULL | 1 | 250000 | 15000 | 12000 |
E-Rows
→ Optimizer 예상
A-Rows
→ 실제 상위 반환 Row
Buffers
→ 실제 Logical Block 작업량
14.1 아래 Row Source부터 본다
최종 SELECT Operation만 보지 않고 Plan Tree 아래에서 처음 E-Rows와 A-Rows가 크게 갈라지는 지점을 찾습니다.
최초 오차 지점
→ 해당 Table·Predicate·Join의 통계를 점검
14.2 Starts가 있는 경우
E-Rows는 Operation의 한 번 Start당 예상 Row로 해석되는 경우가 많고, A-Rows는 화면에서 여러 Starts의 총 Output으로 표시될 수 있습니다.
Starts = 1
→ E-Rows와 A-Rows 직접 비교 가능
Starts = 10,000
→ Actual per Start ≈ A-Rows / Starts
→ 또는 Expected Total ≈ E-Rows × Starts
반복 Nested Loops·Subquery에서는 비교 단위를 맞추지 않으면 추정 오차를 잘못 판단할 수 있습니다.
14.3 Buffers 합산 주의
상위 Row Source의 Runtime Statistics는 하위 작업을 포함할 수 있습니다. 모든 Plan Line의 Buffers를 단순 합산하지 않습니다.
15. 원인별 개선 선택
| 최초 오차 원인 | 확인 | 후보 개선 |
|---|---|---|
| Row·Block 규모 변화 | NUM_ROWS, BLOCKS, DML | Table Statistics 재수집 |
| 값 편중 | Histogram·Bind 분포 | 필요한 Column Histogram |
| Column 상관관계 | 복합 Predicate | Column Group Statistics |
| 함수·표현식 | Expression Predicate | Expression Statistics·FBI |
| 범위 밖 최신값 | Low/High·Data Max | Statistics Refresh·Partition 전략 |
| Statistics 없음·부족 | Notes·Dynamic Sampling | 영구 Statistics 또는 Dynamic 설정 |
| Partition 불일치 | Global·Partition Stats | Granularity·Incremental 운영 |
| SQL 의미·Data Type | Predicate·Bind | SQL·Bind Type 개선 |
통계를 무조건 전체 재수집하는 대신 필요한 범위를 선택합니다.
16. 적용 판단 절차
1. SQL_ID·Child Cursor·실제 Bind·Optimizer 환경을 확정한다.
2. Plan Tree 아래에서 최초 E-Rows·A-Rows 오차 지점을 찾는다.
3. Starts를 반영해 예상·실제 비교 단위를 맞춘다.
4. Table NUM_ROWS·BLOCKS·Sample·LAST_ANALYZED를 확인한다.
5. Predicate Column의 NDV·NULL·Density·Histogram·Low/High를 확인한다.
6. Stale Percent·DML 변화·Partition 범위를 확인한다.
7. 편중·상관·Expression·Missing Statistics로 원인을 분류한다.
8. 필요한 Statistics만 Gather·Extended·Dynamic 방식으로 보완한다.
9. 동일 Bind·Fetch에서 Plan·A-Rows·Buffers·Reads·Elapsed를 재검증한다.
10. Plan 변화·Cursor Invalidations·다른 SQL 회귀를 Monitoring한다.
자주 혼동하는 판단
| 혼동 | 정확한 기준 |
|---|---|
| NUM_ROWS는 현재 COUNT(*)다 | Statistics 수집·유지 시점의 Object Row 통계다 |
| BLOCKS는 Segment 할당 Block이다 | Optimizer Statistics의 Used Block이며 Segment View와 구분한다 |
| SAMPLE_SIZE가 작으면 무조건 나쁘다 | AUTO_SAMPLE_SIZE·Algorithm과 필요한 Statistics 종류를 함께 본다 |
| DENSITY는 항상 1/NDV다 | Histogram이 없을 때 그렇고 Histogram이 있으면 의미가 달라진다 |
Equality Cardinality는 항상 (Rows-Nulls)/NDV다 | Oracle의 가장 단순 공식은 Rows/NDV이며 실제 계산은 더 복잡하다 |
| LOW/HIGH가 분포를 모두 설명한다 | 통계상 범위이며 Histogram과 다르다 |
| STALE_STATS=NO면 정확하다 | 변경률 임계치만 통과했으며 편중·상관·범위 밖 문제는 남는다 |
| 100% Sample이면 모든 추정이 정확하다 | 상관·표현식·Bind·SQL 구조 문제는 별도다 |
| E-Rows≠A-Rows이면 전체 통계를 재수집한다 | 최초 오차 원인에 맞는 통계를 선택한다 |
| Starts가 커도 E-Rows와 A-Rows를 그대로 비교한다 | Per-Start 또는 Total 기준을 맞춘다 |
개념 확인 문제
문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.
01Optimizer Statistics와 Runtime Statistics의 목적 차이를 설명하시오.
두 통계의 차이
- Optimizer Statistics는 실행 전에 Selectivity·Cardinality·Cost를 추정해 Plan을 선택하기 위한 Object 요약값입니다.
- Runtime Statistics는 특정 Cursor 실행의 Starts·A-Rows·Buffers·Reads·시간을 측정한 값입니다.
02NUMROWS, BLOCKS, AVGROWLEN, SAMPLESIZE를 설명하시오.
Table Statistics
- NUM_ROWS는 Object의 Statistics Row 수입니다.
- BLOCKS는 Statistics에 기록된 사용 Data Block 수입니다.
- AVG_ROW_LEN은 Row Overhead를 포함한 평균 Row Byte 길이입니다.
- SAMPLE_SIZE는 Statistics 수집에 사용된 Sample Row 수입니다.
03NUMDISTINCT, NUMNULLS, LOWVALUE, HIGHVALUE, DENSITY를 설명하시오.
Column Statistics
- NUM_DISTINCT는 Non-NULL Distinct Value 수입니다.
- NUM_NULLS는 NULL Row 수입니다.
- LOW_VALUE·HIGH_VALUE는 RAW 형식의 통계상 최솟값·최댓값입니다.
- DENSITY는 값 Selectivity 계산에 사용되며 Histogram 유무에 따라 의미가 다릅니다.
04Histogram이 없는 단순 Equality에서 Oracle의 공식과 Non-NULL 평균 빈도를 구분하시오.
단순 공식 구분
- Oracle 문서의 가장 단순한 Equality 모델은 Selectivity=1/NDV, Cardinality=NUM_ROWS/NDV입니다.
- Data의 Non-NULL 값당 평균 빈도는
(NUM_ROWS-NUM_NULLS)/NDV입니다. - 실제 E-Rows는 Density·Histogram·Predicate·내부 보정을 반영할 수 있습니다.
05Histogram 유무에 따라 DENSITY의 의미가 달라지는 이유를 설명하시오.
DENSITY
- Histogram이 없으면 DENSITY는 1/NUM_DISTINCT입니다.
- Histogram이 있으면 Endpoint 관계를 반영하므로 모든 값의 Selectivity를 단일 Density로 계산할 수 없습니다.
- 실제 Bind가 인기값인지 비인기값인지 확인합니다.
06STALESTATS, STALEPERCENT, LASTANALYZED를 함께 봐야 하는 이유를 설명하시오.
Stale 해석
- LAST_ANALYZED는 수집 시각입니다.
- STALE_STATS는 Monitoring 변경량과 STALE_PERCENT 임계치에 기반합니다.
- NO라도 특정 값 편중·상관관계·High Value 밖 신규 Data 문제는 남을 수 있습니다.
07Global·Partition Statistics가 불일치할 때 발생할 수 있는 문제를 설명하시오.
Partition Statistics
- Pruned Query는 대상 Partition Row·Block 분포가 중요합니다.
- 여러 Partition Query는 Global Statistics가 전체 Cardinality를 적절히 표현해야 합니다.
- 신규·교환 Partition과 오래된 Global Statistics가 섞이면 Join·Access Path 추정이 틀릴 수 있습니다.
08Column Group·Expression·Dynamic Statistics의 적용 조건을 설명하시오.
보조 Statistics
- Column Group은 같은 Table의 상관 Column Predicate를 보완합니다.
- Expression Statistics는 함수·계산식 Predicate 분포를 보완합니다.
- Dynamic Statistics는 Missing·Stale·Insufficient Statistics를 Parse 중 Sample로 일부 보완합니다.
09Starts가 있는 Plan에서 E-Rows·A-Rows를 올바르게 비교하는 방법을 설명하시오.
Starts 비교
- Starts=1이면 E-Rows와 A-Rows를 직접 비교할 수 있습니다.
- Starts가 크면 Actual per Start를 A-Rows/Starts로 보거나 Expected Total을 E-Rows×Starts로 계산해 단위를 맞춥니다.
- Nested Loops 반복을 고려하지 않으면 추정 오차를 잘못 판단할 수 있습니다.
10최초 Cardinality 오차 지점에서 원인에 맞는 Statistics를 선택하는 절차를 설명하시오.
진단 절차 - Plan 아래에서 최초 E/A 오차 Operation을 찾습니다. - Table·Column·Partition Statistics와 실제 Bind를 확인합니다. - 원인을 규모 변화·편중·상관·표현식·범위 밖 값·Missing Statistics로 분류합니다. - 필요한 Statistics만 수집·확장한 뒤 동일 조건에서 Plan·Runtime과 다른 SQL 회귀를 재검증합니다.