|
Q: 전체 Row 수의 5% 정도 이하일 경우에는 Index Lookup 이 유리하고, 그 이상이라면 Table Full Scan 이 유리한가요? A: 질문이 잘못 되었다. |
|---|
Tip Index Scan 과 Table Full Scan 중 유리한 쪽을 결정하는 Magic Number 는 없다, CBO 는 각각의 Cost 를 기계적으로 계산해서 Cost 가 더 낮은 Operation 을 선택한다. |
| Table Full Scan Cost |
|---|
| Blocks | 100 | |
| MBRC | 4 | db_file_multiblock_read_count |
| sreadtim | 5 | Single Block I/O 의 평균 수행 시간(ms) |
| mreadtim | 10 | Multi Block I/O 의 평균 수행 시간(ms) |
| Single Block I/O Count + | 0 |
| Adjusted Multi Block I/O Count + | Multi Block I/O Count * 가중치 = (Blocks / MBRC) * (mreadtim / sreadtim) = ( 100 / 4 ) * ( 10 / 5 ) = 50 |
| Adjusted CPU Count | <Small Value> (0.xxxx) |
| Index Scan Cost |
|---|
| Blevel | 2 | Root Block 에서 Leaf Block 까지 찾아가는 Cost | |
| + | Leaf Blocks * Index Selectivity | 4 * 1 / 4 | 조건에 맞는 Index Leaf Block 을 읽는 Cost |
| + | Clustering Factor * Table Selectivity | 8 * 1 / 5 | 조건에 맞는 Table Block 을 읽는 Cost |
| + | Adjusted CPU Count | <Small Value> (0.xxxx) |
| Index Selectivity 와 Table Selectivity 의 차이점 |
|---|
create table t1 (c1 int, c2 int, c3 int, c4 int);
create index t1_n1 on t1(c1, c2, c3);
...
-- Selectivity 는 다음과 같다고 가정한다.
-- Selectivity (c1 = 1) = 0.1
-- Selectivity (c3 = 2) = 0.2
select * from t1 where c1 = 1 and c3 = 2;
| Index Selectivity | Selectivity(c1 = 1) | 0.1 | c1 = 1 and c3 = 2 조건은 c1 = 1 조건과 동일 |
| Table Selectivity | Selectivity(c1 = 1) * Selectivity(c3 = 2) | 0.02 (0.1 * 0.2) | c3 =2 조건은 Index 의 Filtering 조건으로는 사용될수 없지만, Table 로 나머지 Column 을 읽으러 가야 할지의 여부를 결정하는 Filtering 조건으로는 사용됨 |
| Dirty Estimation |
|---|
| Total Rows | 100,000 |
| Total Blocks | 10,000 |
| MBRC | 10 |
| Index Height | 3 (Blevel = 2) |
| Leaf Blocks | 100 |
| Clustering Factor | 50,000 |
| Index Selectivity | Table Selectivity |
| Index Lookup Cost | Table Scan Cost |
| Blevel + (Leaf Blocks * Selectivity) + (Clustering Factor * Selectivity) | Table Blocks / MBRC |
| 2 + (100 * S) + (50000 * S) | 10000 / 10 |
| (50000 + 100) * S | 10000 / 10 - 2 |
| S | (10000/10 - 2) / (50000 + 100) = 0.019 (2%) |
| Execution Plan (좋은 Clustering Factor) | ||||||
|---|---|---|---|---|---|---|
| {code:sql} explain plan for select /*+ good clsf */ * from t_clsf where c1 between 1 and 100; {code} | ||||||
| {code:sql} | Id | Operation | Name | Rows | Bytes | Cost (%CPU) |
| 0 | SELECT STATEMENT | 100 | 700 | 3 (0) | >> 3 | 1 | TABLE ACCESS BY INDEX ROWID | T_CLSF | 100 | 700 | 3 (0) | >> 3 - 2 = 1 |
| INDEX RANGE SCAN | T_CLSF_I1 | 100 | 2 (0) | >> 2 {code} |
| Execution Plan (나쁜 Clustering Factor) | ||||||
|---|---|---|---|---|---|---|
| {code:sql} explain plan for select /*+ bad clsf index(t_clsf) */ * from t_clsf where c2 between 1 and 100; {code} | ||||||
| {code:sql} | Id | Operation | Name | Rows | Bytes | Cost (%CPU) |
| 0 | SELECT STATEMENT | 100 | 700 | 97 (0) | >> 97 | 1 | TABLE ACCESS BY INDEX ROWID | T_CLSF | 100 | 700 | 97 (0) | >> 97 - 2 = 95 |
| INDEX RANGE SCAN | T_CLSF_I2 | 100 | 2 (0) | >> 2 {code} | ||
Info TABLE ACCESS BY INDEX ROWID(Id:1) : Index Key 값을 확인한 후 ROWID 를 이용해 Table 까지 찾아가는 Cost INDEX RANGE SCAN(Id:2) : Index 의 Root Block 에서 Leaf Block 까지 찾아가는 Cost + Index Leaf Block 을 읽는 Cost | ||||||||||||||||||||
Tip 이런 차이는 대부분 Clustering Factor 값의 차이에 의해 발생한다. |