Index
μΈλ±μ€λ ν μ΄λΈμ λν λμ μλλ₯Ό λνκΈ° μν΄ μ¬μ©λλ μ€λΈμ νΈμ λλ€. μ λ ¬λ μνλ‘ λ°μ΄ν°κ° μ μ₯λμ΄ λΉ λ₯Έ μλλ‘ μνλ λ°μ΄ν°μ μ κ·Όν μ μμ΅λλ€. νμ§λ§, μΈλ±μ€λ₯Ό μ¬μ©νλ€κ³ ν΄μ 무쑰건 μλκ° λΉ λ₯Έ κ²μ μλλλ€. ν μ΄λΈμ μ 체 λ°μ΄ν°λ₯Ό μΆλ ₯νλ κ²½μ°μλ μΈλ±μ€μ νμ보λ€λ ν μ΄λΈμ μ 체 νμνλκ²μ΄ λΉ λ¦ λλ€. κ·Έλμ μ£Όλ‘ νμνλ λ°μ΄ν°κ° λ§μλ° λ°νλλ λ°μ΄ν°κ° μ μ κ²½μ° μΈλ±μ€λ₯Ό μ¬μ©νκ² λ©λλ€. μ΄λ° μΈλ±μ€λ₯Ό μ¬μ©ν λ μ΅ν°λ§μ΄μ λ κ°μ μ΅μ νλ λ°©λ²μΌλ‘ νμμ ν©λλ€. μΈλ±μ€μλ μλμ νμ λ°©μμ΄ μκ³ νλμ© μ΄ν΄λ³΄λλ‘ νκ² μ΅λλ€.
- Index Unique Scan
- Index Range Scan
- Index Full Scan
- Index Fast Full Scan
- Index Skip Scan
μ€μ΅νκ²½
OS : Red Hat Enterprise Linux Server release 6.10
DB : Oracle 11.2.0.1
SID : orcl
user : jamong
ν μ΄λΈ ꡬ쑰
SYS@orcl> create table jamong.departments as select * from hr.departments;
SYS@orcl> create table jamong.employees as select * from hr.employees;
SYS@orcl> alter table jamong.departments add constraint pk_departments primary key(department_id);
SYS@orcl> alter table jamong.employees add constraint pk_employees primary key(employee_id);
JAMONG@orcl> alter session set statistics_level=all;
HR κ³μ μ κΈ°λ³Έ ν μ΄λΈμ λ°μ΄ν°λ₯Ό jamong κ³μ μΌλ‘ μ΄λνμ¬ μ¬μ©νκ³ , 컀μμ μ‘΄μ¬νλ μ€νκ³νμ μμλ‘ νμΈνκΈ° μν΄ statistics_levelμ allλ‘ μ€μ νμ΅λλ€.
xplan.sql
set linesize 150
set pagesize 100
select * from table(dbms_xplan.display_cursor(null,null,'allstats last cost'));
μ€ν κ³νμ λν μμΈ λ΄μ©μ μλ κΈμμ νμΈν μ μμ΅λλ€.
1. Index Unique Scan
Index Unique Scanμ κ²°κ³Όλ‘ νλμ κ±΄μ΄ λ°νλ λ μ¬μ©λκ³ μΉΌλΌμ΄ μ μΌν κ°μΌλ‘ ꡬμ±λμ΄μΌ ν©λλ€. μ¦ Primary Keyμ κΈ°λ³Έμ μΌλ‘ μμ±λλ μΈλ±μ€μ λλ€. 쑰건 κ²μμ΄ λ¨μΌ(=)μΈ κ²½μ° μ¬μ©νκ²λ©λλ€.
μμ
JAMONG@orcl>
select
employee_id
,first_name
,last_name
,salary
from employees
where employee_id = 100;
JAMONG@orcl> @xplan
INDEX UNIQUE SCANμ ν΅ν΄ νλμ κ°λ§ λ°μμ μ¬μ©νκΈ° λλ¬Έμ μΈλ±μ€ μμμ νλμ λΈλ‘μ μ½κ³ ν μ΄λΈμ μ κ·Όνμ¬ νλμ λΈλ‘μ μ½μ΄ μ΄ 2λ²μ λ Όλ¦¬μ λΈλ‘ μ½κΈ°λ₯Ό νμ΅λλ€.
νΉμ§
- μΉΌλΌμ κ°μ΄ μ μΌν Primary Keyμ μ¬μ©λ Index
- λλ± μ‘°κ±΄ "="
- Single Block
2. Index Range Scan
Index Range Scanμ κ°μ₯ μΌλ°μ μΈ Indexμ νμ λ°©μμ λλ€. Indexλ₯Ό μμ§ νμ ν νμν λ²μκΉμ§λ§ νμμ νλ λ°©μμ λλ€. μΈλ±μ€μ λ°μ΄ν°λ μ λ ¬λ μνλ‘ μ μ₯μ΄ λλ―λ‘ λ²μμ λν νμμ΄ νμν λ ν¨μ¨μ μΌλ‘ λ°μ΄ν°λ₯Ό νμν μ μμΌλ©° 리ν λΈλ‘μμ λ€μ 리νλΈλ‘μ μ 보λ₯Ό κ°κ³ μμ΄ λ€μ λΈλμΉ λΈλ‘μ μ½μ νμμμ΄ λ€μ λ°μ΄ν°λ₯Ό λ°λ‘ μ½μ μ μμ΅λλ€. μ΄λ° νΉμ§μ μ νμ©νλ©΄ μ λ ¬μμ μ μλ΅νκ±°λ μ΅λκ°, μ΅μκ°μ μ°Ύλλ° μ μ©νκ² νμ©λ μ μμ΅λλ€.
μμ
JAMONG@orcl> create index employees_dept_idx on employees(department_id);
JAMONG@orcl>
select
employee_id
,first_name
,last_name
,department_id
,salary
from employees
where department_id > 80
order by department_id;
JAMONG@orcl> @xplan
department_id μΉΌλΌμΌλ‘ μΈλ±μ€λ₯Ό μμ±νκ³ Index Range Scanμ μ¬μ©νλ μμλ₯Ό νμΈν΄λ΄€μ΅λλ€. 쿼리μμ department_idλ‘ μ λ ¬νλ μμ μ μμ²νλλ° μΈλ±μ€μμ²΄κ° μ λ ¬λμνλ‘ μ μ₯λμ΄μμ΄ λ°λ‘ μ λ ¬μμ μ νμ§ μλ κ²μ νμΈν μ μμ΅λλ€.
JAMONG@orcl>
select
employee_id
,first_name
,last_name
,department_id
,salary
from employees
where department_id > 80
order by department_id desc;
JAMONG@orcl> @xplan
λκ°μ 쿼리λ₯Ό λ΄λ¦Όμ°¨μμΌλ‘ μ λ ¬νμ λμ μ€νκ³νμ λλ€. Index Range Scanμ μ§ννλλ° DescendingμΌλ‘ νμνλ κ²μ νμΈν μ μμ΅λλ€. μ΄λ μ€λ¦μ°¨μμΌλ‘ μ λ ¬λμ΄ μλ μΈλ±μ€λ₯Ό μμμλΆν°κ° μλ λ€μμλΆν° νμνμ¬ κ²°κ³Όλ₯Ό λ°ννλ κ²μ λλ€.
μ²μλΆν° μΈλ±μ€μ λ°μ΄ν°λ₯Ό λ΄λ¦Όμ°¨μμΌλ‘ μ μ₯νλ descending indexλ₯Ό μμ±νλ λ°©λ²λ μμ΅λλ€.
JAMONG@orcl> drop index employees_dept_idx;
JAMONG@orcl> create index employees_dept_idx on employees(department_id desc);
JAMONG@orcl>
select
employee_id
,first_name
,last_name
,department_id
,salary
from employees
where department_id > 80
order by department_id desc;
JAMONG@orcl> @xplan
λ°μ΄ν°κ° λ΄λ¦Όμ°¨μμΌλ‘ μΈλ±μ€μ μ μ₯λμ΄μμ΄ λ΄λ¦Όμ°¨μ κ²°κ³Όλ₯Ό μμ²ν λ μΌλ° Index Range Scanμ ν©λλ€. Descending Index Range Scanμ μ΅λκ°μ ꡬν λ μ¬μ©λ©λλ€. max κ°μ ꡬν λ μΈλ±μ€λ‘λΆν° κ°μ₯ λμ μλ ν νλλ§ μ½μ΄μ€λ©΄ λκΈ°λλ¬Έμ μ 체 λ°μ΄ν°λ₯Ό νμν νμκ° μμ΅λλ€. λ§μ½ μ΅ν°λ§μ΄μ κ° λ€λ₯Έ μ νμ νλ€λ©΄ ννΈλ₯Ό μ¬μ©ν΄μ νλμ νλ§ μ½λλ‘ μ λν μ μμ΅λλ€.
νΉμ§
- λΉκ΅μ‘°κ±΄(>,<) μ¬μ© μ --> Unique Index
- Non Unique Index μ¬μ©μ μ¬μ©λ μ μμ
- μμ§ νμ ν νμν λ²μκΉμ§λ§ νμ
- Single Block Read
3. Index Full Scan
Index Full Scanμ 첫λ²μ§Έ 리νλΈλ‘κΉμ§ μμ§μ νμ ν, μΈλ±μ€ μ 체λ₯Ό νμνλ λ°©λ²μ λλ€. μ£Όλ‘ ν μ΄λΈμμ Table Full Scanμ λΆλ΄μ΄ ν¬κ±°λ μ λ ¬μμ μ μλ΅νκΈ° μν΄ ν μ΄λΈ μ 체λ₯Ό νμνλ κ²λ³΄λ€ Indexλ₯Ό μ¬μ©νλ κ²μ΄ μ 리ν©λλ€. κ·Έλ°λ° μ΄ λ°©λ²μ μμ±λ μΈλ±μ€κ° μμ΄ μ¬μ©λ λ°©λ²μΌλ‘ Index Range ScanμΌλ‘ μ λνλ κ²μ΄ μ’μ΅λλ€.
μμ
JAMONG@orcl> drop index employees_dept_idx;
JAMONG@orcl> create index employees_dept_idx on employees(department_id);
JAMONG@orcl>
select
*
from employees
where department_id is not null
order by department_id;
JAMONG@orcl> @xplan
department_idμ λ€μ μΈλ±μ€λ₯Ό μμ±νμ΅λλ€. μ°μ 쑰건μ μ range scanμ νΌνκΈ° μν΄ is not null 쑰건μ λΆμ¬νμ΅λλ€. κ·Έλ¦¬κ³ department_idλ₯Ό κΈ°μ€μΌλ‘ μ λ ¬νλ μμ μ νμ΅λλ€. μ΄λ² μμλ μ λ ¬μμ μ μλ΅νκΈ° μν΄ Index Full Scanμ μ¬μ©ν κ² μ λλ€. is not null μ‘°κ±΄μ΄ μλλλΌλ Full Scanμ μ¬μ©ν μ μμ΅λλ€. νμ§λ§ μ΄λ² μμμμλ λ¨μΌ μΉΌλΌ μΈλ±μ€λ₯Ό μ¬μ©νκΈ° λλ¬Έμ 쑰건μ λΆμ¬νλ©΄ Range ScanμΌλ‘ νμνκΈ° λλ¬Έμ not null 쑰건μ μ¬μ©νμ΅λλ€. μ΄λ° μμΌλ‘ μ λ ¬μμ μ μλ΅νκΈ° μν΄ λ§μ΄ μ¬μ©λ©λλ€.
JAMONG@orcl> select count(*) from employees;
JAMONG@orcl> @xplan
count ν¨μλ₯Ό μ¬μ©ν λλ Index Full Scanμ μ¬μ©ν©λλ€. μ°μ 쑰건μ μ΄ μλλ°λ λΆκ³ νκ³ Indexλ₯Ό μ¬μ©ν©λλ€. count ν¨μλ ν μ΄λΈ μ‘μΈμ€λ₯Ό ν νμμμ΄ μΈλ±μ€λ§μΌλ‘λ Countκ°μ λ°μμ¬ μ μμ΅λλ€. λ°μ΄ν° μ μ²΄κ° μλ ν μ΄λΈμ λΉν΄μ μΈλ±μ€μ μ μ₯λμ΄ μλ λ°μ΄ν°λ μΌλΆ μΉΌλΌμ λλ€. κ·Έλμ λλΆλΆ μΈλ±μ€κ° μ°¨μ§νλ λ°μ΄ν°μ 곡κ°μ΄ ν μ΄λΈλ³΄λ€ ν¨μ¬ μ κΈ° λλ¬Έμ ν μ΄λΈ μ μ²΄λ³΄λ€ μΈλ±μ€ μ 체λ₯Ό νμνλ λΉμ©μ΄ μ μ΅λλ€.
JAMONG@orcl> select max(department_id) from employees;
JAMONG@orcl> @xplan
JAMONG@orcl> select min(department_id) from employees;
JAMONG@orcl> @xplan
λ€μ Index Full Scanμ κ°μ₯ λ§μ΄ μ¬μ©νλ λΆλΆμ΄ maxμ minν¨μλ₯Ό μ¬μ©ν λ μ λλ€. Index Full Scanμ μΈλ±μ€ μ 체λ₯Ό νμΈνλλ° Min Maxλ₯Ό ꡬν λλ μΈλ±μ€μ μμ νΉμ λ νλ² κ±΄λ§ νμΈνκ³ νμμ λλ΄λ λ°©λ²μΌλ‘ 1κ°μ λΈλ‘μ μ½μ΄ κ²°κ³Όλ₯Ό μ»μ μ μμ΅λλ€.
νΉμ§
- μΈλ±μ€μ λͺ¨λ λΈλ‘μ μ½λλ€.
- μ λ ¬ μμ μ μλ΅νκΈ° μν΄ μ¬μ©λλ€.
- Not Null 쑰건μΌλ‘λ μΈλ±μ€ νμμ΄ κ°λ₯νλ€.
- Single Block Read
Full Table Scanκ³Ό Index Full Scanμ μ°¨μ΄μ ?
κ°μ₯ ν° μ°¨μ΄μ μ Multi-Block Readκ° κ°λ₯ μ¬λΆ μ λλ€. Full Table Scanμ Multi-Block Readκ° κ°λ₯νμ§λ§ Index Full Scanμ 리νλΈλ‘μ μΌμΌν λ°©λ¬ΈνκΈ° λλ¬Έμ Single Block Readλ°μ ν μ μμ΅λλ€. κ·Έλμ λλ‘λ Full Table Scanμ μ±λ₯μ΄ λ μ’μ λκ° μμ΅λλ€.
4. Index Fast Full Scan
Index Fast Full Scanμ λ§ κ·Έλλ‘ Index Full Scanλ³΄λ€ λΉ λ₯΄λ€. μ λΆλ₯Ό νμνλ©΄μ λ λΉ λ₯΄κ² κ²°κ³Όλ₯Ό μ»μ μ μλ μ΄μ λ Multi-Block Readκ° κ°λ₯νκΈ° λλ¬Έμ λλ€. νμ§λ§ μ΄λ‘ μΈν΄ μ λ ¬λ μνλ‘ λ°μ΄ν°λ₯Ό λ°μ μ μλ€λ μ νμ΄ μμ΅λλ€. Index Full Scanμ λ°μ΄ν°μ λ Όλ¦¬μ μΈ μμλ‘ κ²°κ³Όλ₯Ό μ»μ§λ§ Index Fast Full Scanμ λ°μ΄ν°μ 물리μ μ μ₯ ꡬ쑰μ μμλ‘ λ°μμ€κ³ κ·Έλμ Multi-Block Readκ° κ°λ₯ν©λλ€.
μμ
JAMONG@orcl> select count(employee_id) from employees;
JAMONG@orcl> @xplan
Employees ν μ΄λΈμμ countλ‘ μ 체 κ²°κ³Όλ₯Ό λ°μμμλ Index Full Scanμ μ¬μ©νλ κ²μ νμΈν μ μμ΅λλ€. κ·ΈλΌ λμ©λμ© ν μ΄λΈμ νλ μμ±ν΄μ λκ°μ μ§μλ₯Ό ν΄λ³΄κ² μ΅λλ€.
JAMONG@orcl> create table test as select * from employees;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> insert into test select * from test;
JAMONG@orcl> create index test_emp_id_idx on test(employee_id);
JAMONG@orcl> select count(employee_id) from test;
JAMONG@orcl> @xplan
κΈ°μ‘΄μ 107κ°μλ employees ν μ΄λΈμ λλ΅ 90λ§κ±΄μ λ°μ΄ν°λ₯Ό κ°λλ‘ ν μ΄λΈμ μμ±νμ΅λλ€. μ΄ν λκ°μ΄ employee_idμ μΈλ±μ€λ₯Ό μμ±ν΄μ£Όκ³ κ°μ 쿼리λ₯Ό μ§μ νμ΅λλ° Index Fast Full Scanμ μ¬μ©νμ΅λλ€. μ΄λ λ°μ΄ν°κ° λμ΄λλ©΄μ Index Fast Full Scanμ΄ λΉμ©μ΄ λ μ κ² λλ κ²μΌλ‘ μ΅ν°λ§μ΄μ κ° νλ¨νκΈ° λλ¬Έμ λλ€.
Index Fast Full Scanμ μ£Όλ‘ ννΈλ₯Ό μ¬μ©ν΄μ Multi Block Readκ° κ°λ₯νλλ‘ μΏΌλ¦¬νλμ νλ κ² κ°μ΅λλ€. Index Full Scanμ μ¬μ©νλλ° Disk I/Oκ° λ§μ΄ λ°μν λ μ¬μ©νλ©΄ ν¨κ³Όμ μ λλ€. Index Fast Full Scanμ μ¬μ©νλ©΄ Disk I/Oλ λΉμ·ν μ μμ΄λ νλ²μ΄ μ½μ΄λ€μ΄λ λΈλ‘μ΄ db_file_multiblock_read_count νλΌλ―Έν° λ§νΌ μ΄κΈ° λλ¬Έμ μμ°¨μ μΌλ‘ λ°μ΄ν°λ₯Ό μ½μ΄μ€κΈ° μν΄ λ°μνλ λκΈ° μ΄λ²€νΈλ₯Ό μ€μΌ μ μμ΅λλ€.
νΉμ§
- Index Full Scanλ³΄λ€ λΉ λ¦
- 물리μ μμλλ‘ νμ
- Multi Block Read κ°λ₯
- λ³λ ¬ μ²λ¦¬ κ°λ₯
5. Index Skip Scan
Index Skip Scanμ Multi Column Indexμμ νν μΉΌλΌμ 쑰건μ μ μ¬μ©ν λ νμ©ν μ μμ΅λλ€. μ±λ³μ²λΌ μ λ μΉΌλΌμ κ³ μ κ°μ κ°μκ° μ κ³ νν μΉΌλΌμ κ³ μ κ°μ΄ λ§μ λ ν¨κ³Όμ μ λλ€. μλ₯Ό λ€μ΄ λΆμκ° 10,20,30,40 μΈ νμ¬κ° μλλ° μ§μμ΄ 1000λͺ μ λλ€. κ°κ° 500,100,200,200 λͺ μ μ§μμ΄ μμ΅λλ€. μ°λ¦¬κ° μκ³ μΆμ λ΄μ©μ κΈμ¬κ° 5000 ~ 7000 μ¬μ΄μΈ μ§μμ λλ€. μμ±λ μΈλ±λ (λΆμλ²νΈ,κΈμ¬)λ‘ κ²°ν©λ μΈλ±μ€κ° μμ΅λλ€. λ§μ½ Index Skip Scanμ μ¬μ©νλ©΄ 10λ² λΆμμμ 5000 ~ 7000μΈ μ§μμ μ°Ύκ³ κ·Έ μ΄ν 10λ² λΆμμ λ°μ΄ν°λ νμΈν νμκ° μκΈ° λλ¬Έμ 20λ² λΆμλ‘ λμ΄κ°μ λκ°μ΄ λ°λ³΅ν©λλ€. μ΄λ°μμΌλ‘ νμμλ λΆλΆμ λν΄μ 건λλ΄λ€λ©΄ Full Table Scanλ³΄λ€ μ±λ₯μ΄ μ’μ μ μμ΅λλ€.
μμ
JAMONG@orcl> create index employees_dept_sal_idx on employees(department_id,salary);
JAMONG@orcl>
select /*+index_ss(employees employees_dept_sal_idx)*/ *
from employees
where salary between 5000 and 7000;
λ§λ ν μμ 쿼리λ₯Ό μ°ΎκΈ° νλ€μ΄ ννΈλ₯Ό μ¬μ©ν΄μ κ²°κ³Όλ₯Ό μΆλ ₯ν΄λ΄€μ΅λλ€.
νΉμ§
- κ²°ν© μΈλ±μ€μ μ ν μΉΌλΌμ΄ 쑰건μμ μμ΄λ μ¬μ© κ°λ₯
- Single Block Read
- μ λμ»¬λΌ Distinct Value μ κ³ νν μ»¬λΌ Distinct Value λ§μ λ ν¨κ³Όμ
λκΈ