Join
RDBMS์์๋ ์ ๊ทํ์ ์ํด ์ฐ๊ด๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ๊ฐ์ ํ ์ด๋ธ๋ก ๋๋๊ฒ ๋ฉ๋๋ค. ๊ทธ๋์ ์ํ๋ ํ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ธฐ ์ํด ์ฌ๋ฌ๊ฐ์ ํ ์ด๋ธ์ ์ฐ๊ฒฐํ์ฌ ์ฌ์ฉํ๋๋ฐ ์ด๋ฅผ Join์ ํตํด์ ํ ์ ์์ต๋๋ค. Join์์ ์ ํ ๋๋ ์ตํฐ๋ง์ด์ ๋ ์ด๋ค ๋ฐฉ์์ผ๋ก ์กฐ์ธ์ ํ ์ง ์คํ๊ณํ์ ์ธ์ฐ๊ฒ ๋ฉ๋๋ค. ์ด๋ฒ ๊ธ์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ด๋ถ์ ์ผ๋ก ์ด๋ป๊ฒ ์กฐ์ธ์ ํ๋์ง ์๋ 3๊ฐ์ง ๋ฐฉ์์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค.
- Nested Loop Join
- Sorted Merge Join
- Hash Join
์ค์ตํ๊ฒฝ
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> create index employees_dept_idx on employees(department_id);
JAMONG@orcl> alter session set statistics_level=all;
HR ๊ณ์ ์ ๊ธฐ๋ณธ ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ jamong ๊ณ์ ์ผ๋ก ์ด๋ํ์ฌ ์ฌ์ฉํ๊ณ , ์ปค์์ ์กด์ฌํ๋ ์คํ๊ณํ์ ์์๋ก ํ์ธํ๊ธฐ ์ํด statistics_level์ all๋ก ์ค์ ํ์ต๋๋ค. test table์ department_id์ ๋ํ ์ธ๋ฑ์ค๋ ์์ฑํด์ค๋๋ค.
xplan.sql
set linesize 150
set pagesize 100
select * from table(dbms_xplan.display_cursor(null,null,'allstats last cost'));
start.sql
conn jamong/jamong
alter session set max_dump_file_size=unlimited;
alter session set events '10046 trace name context forever, level 12';
end.sql
alter session set events '10046 trace name context off';
define _editor=vi
undefine trace
column trace_file new_value trace
SELECT value AS trace_file
FROM v$diag_info
WHERE name = 'Default Trace File';
!tkprof &trace output.trc sys=no
ed output.trc
์คํ๊ณํ์ ํ์ธํ๊ธฐ ์ํ ์คํฌ๋ฆฝํธ๋ฅผ ํธ๋ฆฌ์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ ์ค์ต ์งํํ๊ฒ ์ต๋๋ค. ์คํ ๊ณํ์ ๋ํ ์์ธ ๋ด์ฉ์ ์๋ ๊ธ์์ ํ์ธํ ์ ์์ต๋๋ค.
1. Nested Loop Join
Nested Loop Join์ ๋ฐฉ์์ ๋๊ฐ์ ํ ์ด๋ธ์ ํ์ ๊ฐ๊ฐ ๋ชจ๋ ํ์ธํ์ฌ ์กฐ์ธํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ํํํ์๋ฉด ์ค์ฒฉ๋ for๋ฌธ์ ๋๋ค. inner์ outer loop์ด ์๋ฏ์ด ์กฐ์ธ์๋ dirving๊ณผ driven ํ ์ด๋ธ์ด ์์ต๋๋ค. ์คํ๊ณํ์์ ๋จผ์ ์คํ๋๋ ํ ์ด๋ธ์ด driving ํ ์ด๋ธ์ด๊ณ ๋์ค์ ์คํ๋๋ ๊ฒ์ด driven ํ ์ด๋ธ์ ๋๋ค. ์ค์ฒฉ๋ for ๋ฌธ์ด๋ผ๊ณ ํํํ ์ด์ ๋ ๊ฐ๊ฐ ํ ์ด๋ธ์ ๋ชจ๋ ์ฝ๊ณ ํ์ธํ๋ ๊ฒ์ด์๋๋ผ ๊ฐ ํ๋ณ๋ก ํ์ธํ๊ธฐ ๋๋ฌธ์ ํ์ด ์ ์ ํ ์ด๋ธ์ driving ํ ์ด๋ธ๋ก ์ ์ ํ๋ ๊ฒ์ด ๋น ๋ฅธ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ํ ์กฐ์ธ ์ปฌ๋ผ์ ์ธ๋ฑ์ค๊ฐ ์์ด์ผ ํ ์ด๋ธ ์ ์ฒด๋ฅผ ํ์ํ์ง ์๊ณ ํ์ํ ํ์๋ํด์๋ง ํ์ํ์ฌ ํจ์จ์ ์ ๋๋ค.
์์
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_dept_idx on test(department_id);
์ฑ๋ฅ์ ํ์ฐํ ์ฐจ์ด๋ฅผ ํ์ธํ๊ธฐ ์ํด testํ ์ด๋ธ์ 90๋ง๊ฑด ์ ๋์ ํ ์ด๋ธ๋ก ์์ฑํ์ต๋๋ค. 27๊ฑด์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณ ์๋ departments ํ ์ด๋ธ๊ณผ ์กฐ์ธํด์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ณผ๊ฒ์ ๋๋ค.
JAMONG@orcl> @start
JAMONG@orcl>
select /*+ leading(e) use_nl(d) */ count(*)
from test e, departments d
where e.department_id = d.department_id;
JAMONG@orcl> @end
ํํธ๋ฅผ ์ฌ์ฉํด์ leading --> test ํ ์ด๋ธ์ driving ํ ์ด๋ธ๋ก ์ค์ ํ๊ณ ํน๋ณํ ํํฐ๋ง์์ด Nested Loop Join์ผ๋ก ์คํํ๊ณ ์คํ๊ณํ์ ๊ทธ๋ฆผ์ผ๋ก ๊ทธ๋ ค๋ดค์ ๋ ์์ ๊ฐ์ต๋๋ค. ์คํํ๋๋ฐ 70์ด์ ๋๊ฐ ์์๋ฌ๊ณ ๊ทธ๋ผ diving๊ณผ driven ํ ์ด๋ธ์ ๋ฐ๊พธ๊ณ ์คํํ ํ ๋น๊ตํด๋ณด๊ฒ ์ต๋๋ค.
JAMONG@orcl> @start
JAMONG@orcl>
select /*+ leading(d) use_nl(e) */ count(*)
from test e, departments d
where e.department_id = d.department_id;
JAMONG@orcl> @end
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ดค์๋ driving ํ ์ด๋ธ์ด departments์ผ ๋ ์คํ ์๊ฐ 27์ด๋ก 71์ด๋ณด๋ค 2๋ฐฐ ์ด์ ๋น ๋ฅธ ์๋๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค. ์คํ๊ณํ์ ๋ดค์๋ ์ฝ๋ ๋ธ๋ก์ ๊ฐฏ์๋ ํฌ๊ฒ ์ฐจ์ด๊ฐ ์์ต๋๋ค. ๊ฒฐ๊ณผ๋ ๊ฐ์ผ๋ฏ๋ก ๋ฐํ๋๋ row์ ๊ฐฏ์๋ ๊ฐ์๋ฐ ์๋์ฐจ์ด๋ ํฌ๊ฒ ๋ฉ๋๋ค. count๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋๊ฒ์ผ๋ก Table์ ๋ํ Random Access ํ์์์ด ์ธ๋ฑ์ค๋ง ๊ฐ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ์ด๋ค ์ด์ ๋ก ์ฐจ์ด๊ฐ ๋๊ฑธ๊น์? ๋ฐ๋ก driving ํ ์ด๋ธ์ ํ์ ๊ฐฏ์๊ฐ ๋น๊ต์ ์ ๋ค๋ ์ด์ ์ด๊ณ Nested Loop Join์ด ๋ ์ฝ๋ ํ๋์ฉ ์์ฐจ์ ์ผ๋ก ์กฐ์ธ์์ ์ ํ๋ค๋ ํน์ง์ด ํ์คํ๊ฒ ๋ณด์ฌ์ง๋๋ค.
driving ํ ์ด๋ธ์ด test์ผ๋์ ์ํฉ์ ๋จผ์ ๋ณด๊ฒ ์ต๋๋ค. ๋ ์ฝ๋ ํ๋์ฉ ํ์ธํ๊ธฐ ๋๋ฌธ์ ๋จผ์ TEST_DEPT_IDX๋ฅผ ๊ฐ๊ฐ 90๋ง๋ฒ ํ์ธํ๋ฉด์ PK_DEPARTMENTS ์ธ๋ฑ์ค๋ฅผ Unique Scan์ผ๋ก ํ๋ฒ์ฉ๋ง ํ์ธํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ต๋๋ค. ๊ทธ๋ฆผ์ผ๋ก ํํํ์๋ฉด ์๋์๊ฐ์ด ๋ป์ด๋๊ฐ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ธํฉ๋๋ค.
driving ํ ์ด๋ธ์ด departments์ผ๋๋ ๋ ์ฝ๋๋ฅผ PK_DEPARTMENTS์์ ๋จผ์ ๋ค ํ์ธํ๊ณ ๊ฐ ๋ ์ฝ๋๋ณ๋ก Range Scan์ ํตํด TEST_DEPT_IDX๋ฅผ ํ์ํฉ๋๋ค. ์๋์ ๊ฐ์ ์์ผ๋ก ์ํํฉ๋๋ค.
๊ทธ๋ฆผ์ผ๋ก๋ง ๋ด๋ ํ์ฐํ๊ฒ ์ฐจ์ด๋ฅผ ๋๋์ ์์ต๋๋ค. driving ํ ์ด๋ธ์ ๋ ์ฝ๋๊ฐ ์ ์ ๊ฒฝ์ฐ driven ํ ์ด๋ธ์์ ์ผ์ผํ Root ๋ธ๋ก์ ๊ฑฐ์น๋ ์ผ์ด ์๊ธฐ ๋๋ฌธ์ ํจ์ฌ ๋น ๋ฅธ ์๋๋ก ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค. ๋ฌผ๋ก , ์ธ๋ฑ์ค๊ฐ ๋ชจ๋ ์๋ ํ ์ด๋ธ์ ๊ฒฝ์ฐ์๋ ์ด๋ค ๊ฒฝ์ฐ์๋ ๋ชจ๋ Full Table Scan์ ํ๊ธฐ ๋๋ฌธ์ ์๋ฏธ๊ฐ ์์ต๋๋ค. ๊ทธ๋ผ ์ด๋ฒ์๋ count๊ฐ ์๋ ํ ์ด๋ธ์ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ์ฌ Random Accessํ์ ๋์ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
e_lead.sql
select /*+ leading(e) use_nl(d) */
e.employee_id,
e.first_name,
e.salary,
d.department_id,
d.location_id
from test e, departments d
where e.department_id = d.department_id
and e.employee_id > 150
and d.location_id = 2700;
d_lead.sql
select /*+ leading(d) use_nl(e) */
e.employee_id,
e.first_name,
e.salary,
d.department_id,
d.location_id
from test e, departments d
where e.department_id = d.department_id
and e.employee_id > 150
and d.location_id = 2700;
๊ฒฐ๊ณผ ์ถ๋ ฅ๋๋ ๋ด์ฉ์ด ๋ง์์ script์ ์์ฑ ํ termout ์ต์ ์ ๋๊ณ ์ค์ต์งํํ๊ฒ ์ต๋๋ค.
JAMONG@orcl> set termout off
JAMONG@orcl> @start
JAMONG@orcl> @e_lead
JAMONG@orcl> set termout on
JAMONG@orcl> @end
test Table์ด Driving Table์ธ ๊ฒฝ์ฐ์ ๋๋ค. ์ฐ์ ์ถ๋ ฅํ๋ ๋ฐ์ดํฐ์ ์์ด ๋ง์ Test ํ ์ด๋ธ์ Full Table Scan์ ํตํด ํ์์ํ๋ฉด์ employee_id ๊ฐ 150 ์ดํ์ธ ๋ ์ฝ๋๋ ํํฐ๋งํ๊ฒ์ผ๋ก ๋ด ๋๋ค. ์ฆ 90๋ง๊ฑด์ ์ ๋ถํ์ธํ๋ฉด์ ๋๋ต 45๋ง๊ฑด์ ๋ฐ์ดํฐ๊ฐ ํํฐ๋ง๋ฉ๋๋ค. ๊ทธ๋ค์ 45๋ง๊ฑด์ ๋ํด์ PK_DEPARTMENTS ์ธ๋ฑ์ค์ ์กฐ์ธ์์ ์ํฉ๋๋ค. ์กฐ์ธ๋ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๊ณ departments ํ ์ด๋ธ๊ณผ ๋ค์ ์กฐ์ธํ๊ฒ ๋๋๋ฐ ROWID์ ๋ํ ์กฐ์ธ์ผ๋ก Accessํ๋ฉด์ location_id๊ฐ 2700์ธ ๋ฐ์ดํฐ๋ฅผ ํํฐ๋งํฉ๋๋ค.
driving table์์ 45๋ง๊ฑด์ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ธํ๋๋ฐ ๊ฒฐ๊ณผ๋ก 8000๊ฑด์ ๋์ ๋ฐ์ดํฐ๋ฅผ ์ป๋ ๊ฒ์ ์ฝ์ ๋ฐ์ดํฐ ์ค ์๋นํ ์์ ๋ฒ๋ฆฌ๋ ๊ฒ์ผ๋ก ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ผ๋ก ํ๋จํ ์ ์์ต๋๋ค.
JAMONG@orcl> set termout off
JAMONG@orcl> @start
JAMONG@orcl> @d_lead
JAMONG@orcl> set termout on
JAMONG@orcl> @end
์ด๋ฒ์๋ departments ํ ์ด๋ธ์ด driving ํ ์ด๋ธ์ ๋๋ค. ๊ฐ์ฅ ๋จผ์ Departments Table์ Full Table Scanํ๋ฉด์ location_id๊ฐ 2700์ธ ๋ ์ฝ๋๋ฅผ ํํฐ๋งํด์ 1๊ฑด์ ๋ฐ์ดํฐ๋ฅผ ์ป์ต๋๋ค. ๊ทธ๋ค์ TEST_DEPT_IDX ์ธ๋ฑ์ค๋ฅผ ํ์ํ๋๋ฐ departments ํ ์ด๋ธ์์ ํ๋์ ๋ ์ฝ๋์ ๋ํด์๋ง ํ์ธํ๋ฉฐ ์กฐ์ธํ๋ฉด ๋ฉ๋๋ค. ๊ทธ ์ดํ TEST ํ ์ด๋ธ Access๋ฅผ ํ๋ฉด์ employee_id๊ฐ 150 ๋ณด๋ค ๋์ ์กฐ๊ฑด์ ํํฐ๋งํ๋๋ฐ ๊ณต๊ต๋กญ๊ฒ๋ ์ด์ ์ ํํฐ๋ง๋ ๊ฒฐ๊ณผ๊ฐ ๋ชจ๋ ํด๋น ์กฐ๊ฑด์ ๋ง์กฑํ์ฌ ๋ฒ๋ฆฌ๋ ํ ์์ด ๋ชจ๋ ROWID์ ๋ํด ์กฐ์ธ ์์ ์ ํ๊ฒ๋ฉ๋๋ค.
์คํํ๋๋ฐ ์์๋ ์๊ฐ๋ง ๋น๊ตํด๋ณด๋ฉด 52์ด์์ 1์ด๋ก ์ค์ผ ์ ์์์ต๋๋ค. ๋ช๊ฐ์ง ์กฐ๊ฑด์ ์ฒ๋ฆฌํ์ฌ ์กฐ์ธํ๊ธฐ ์ด์ ์ driving ํ ์ด๋ธ์์ ํํฐ์์ ์ ์งํํ์ฌ driving table์ ํ์ ์ค์ฌ์ฃผ๋ฉด ํ์คํ ์ฑ๋ฅ์ฐจ์ด๋ฅผ ํ์ธํ ์ ์์์ต๋๋ค. ๊ทธ๋งํฐ Nested Loop Join์์๋ driving, driven ํ ์ด๋ธ์ ์ด๋ป๊ฒ ์ง์ ํ๋์ง๊ฐ ์ค์ํ๊ณ ์ธ๋ฑ์ค์ ์์กด์ ์ ๋๋ค.
ํน์ง
- driving ํ ์ด๋ธ ๊ฒฐ์ ํ driven ํ ์ด๋ธ์ ๋ฐ๋ณต์ ์ธ ์ ๊ทผ
- ํ ๋ ์ฝ๋์ฉ ์์ฐจ์ ์ผ๋ก ์ ๊ทผ
- ๋ง์ ์์ ๋ฐ์ดํฐ ์กฐ์ธ ์ Random Access ์ฆ๊ฐ
- Random Access ์์ฃผ์ ์กฐ์ธ ๋ฐฉ์
- ์๋์ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ธ ์ ์ฌ์ฉ
- ๋ถ๋ถ ๋ฒ์ ์ฒ๋ฆฌ์ ์ต์ ํ
- ์ธ๋ฑ์ค ๊ตฌ์ฑ ์ ๋์ด ์ค์
2. Sorted Merge Join
Sorted Merge Join์ ๋๊ฐ์ ํ ์ด๋ธ์ ์กฐ์ธ ์นผ๋ผ์ผ๋ก ์ ๋ ฌํ์ฌ ์กฐ์ธํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์ ๋ ฌ๋ ํ ์ด๋ธ๋ก ์กฐ์ธํ๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ๋ ํจ๊ณผ์ ๋น์ทํฉ๋๋ค. Sorted Merge Join์ Nested Loop Join์ ์กฐ์ธ๊ณผ ์ํ ๊ณผ์ ์ด ๋ค๋ฅด์ง ์์ต๋๋ค. ๋จ, PGA ์์ญ์ ์ด์ฉํ์ฌ ์ ๋ ฌ์์ ์ ํ๊ธฐ ๋๋ฌธ์ ๋์น ํ๋ํ ํ์๊ฐ ์์ด Index๋ฅผ ํตํด Table Accessํ๋ ๊ฒ๋ณด๋ค ๋น ๋ฆ ๋๋ค. ์ด๋ฌ ํ ํน์ฑ์ ๊ฐ๊ณ ์์ด ์กฐ์ธ๋๋ ์นผ๋ผ์ ์ธ๋ฑ์ค๊ฐ ์๋ ๊ฒฝ์ฐ์ ์ ๋ฆฌํ ์ ์์ต๋๋ค.
์ธ๋ฑ์ค๊ฐ ์๋ ๋ํ ์ด๋ธ์ ๋ํด์ Nested Loop Join์ ํ๋ ๊ฒฝ์ฐ driving table์ ๊ฐ๊ฐ ํ์ ๋ํด driven table์ Full Scanํ๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค์ ๋ง์ด ์์กดํ๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ฉด, Sorted Merge Join์ ์ธ๋ฑ์ค๊ฐ ์์ด๋ ์กฐ์ธ์นผ๋ผ์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ ํ inner table ์กฐํ์ outer table์ ๊ฐ์ ๋ํด์๋ง ์กฐ์ธํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค๊ฐ ์๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋ ์ ์๊ณ ์ด๋ฌํ ์ ๋ ฌ ์์ ์ ๋ํ ๋ถํ๋ฅผ ๊ฐ์ํ๋ค๋ฉด Nested Loop Join ๋ณด๋ค ์ ๋ฆฌํ ์ ์์ต๋๋ค.
์์
Sorted Merge Join์ Hash join์ ๋ฑ์ฅ์ผ๋ก ์ฌ์ฉ์ด ๋ง์ด ์ค์ด๋ค์์ต๋๋ค. ํ์ง๋ง ์ฌ์ ํ Sorted Merge Join์ ์ฌ์ฉํ๋๊ฒ ์ ๋ฆฌํ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. Outer ์งํฉ์ด ์ ๋ ฌ๋์ด ์๋ ๊ฒฝ์ฐ์ Non equi join์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ ๋๋ค.
์ฒซ๋ฒ์งธ๋ Outer ์งํฉ์ด ์ ๋ ฌ๋์ด ์๋ ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
JAMONG@orcl>
select
e.employee_id,
e.first_name,
e.salary,
d.department_id,
d.location_id
from employees e, departments d
where e.department_id = d.department_id;
JAMONG@orcl> @xplan
๋ง์ฝ Outer Table์ index๋ฅผ ์ด์ฉํ ํ์์ ํ๋ค๋ฉด Sort Merge Join ์ ์ ๋ ฌ ์์ ์ ๋์ฒดํ ์ ์์ต๋๋ค. ์์ ์ฟผ๋ฆฌ์์๋ Outer Table departments๋ฅผ Index Full Scan์ ์ํด์ Table Access๋ฅผ ํ ํ employees ํ ์ด๋ธ์ ์ฝ์ด sorting ์์ ์ ํฉ๋๋ค. ์ดํ merge ์์ ์ ํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค. ์ด์ ๊ฐ์ด outer table์ ์ธ๋ฑ์ค๋ก ์ ๋ ฌ์์ ์ ๋์ฒดํด์ Sorted Merge Join์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ด๋ฏธ Outer Table์ด ์ ๋ ฌ๋์ด ์๋ ๊ฒฝ์ฐ ์กฐ์ธ์ ์ํด ๋ค์ ์ ๋ ฌ์์ ์ ํ์ง ์์๋ ๋๋ฏ๋ก Sorted Merge Join์ด ์ ๋ฆฌํ ์ ์์ต๋๋ค.
JAMONG@orcl>
select
d.department_name,
e.sal_avg
from
departments d,
(
select
department_id,
avg(salary) as sal_avg
from employees
group by department_id
order by department_id
) e
where e.department_id = d.department_id;
JAMONG@orcl> @xplan
๊ฐ ๋ถ์๋ฅผ ๋ถ์์ ํ๊ท ๊ธ์ฌ์ ํจ๊ป ์ถ๋ ฅํ๋ ์ฟผ๋ฆฌ์ ๋๋ค. e ์งํฉ์ ๋ํด์ groupingํ๊ณ ์กฐ์ธ๋๋ ์นผ๋ผ์ผ๋ก ๋ฏธ๋ฆฌ ์ ๋ ฌ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ตํฐ๋ง์ด์ ๋ Sorted Merge Join์ผ๋ก ์คํ๊ณํ์ ์ ํํฉ๋๋ค.
JAMONG@orcl> create table salgrade(grade number,losal number,hisal number);
JAMONG@orcl> insert into salgrade values(1,0,4000);
JAMONG@orcl> insert into salgrade values(2,4001,8000);
JAMONG@orcl> insert into salgrade values(3,8001,12000);
JAMONG@orcl> insert into salgrade values(4,12001,16000);
JAMONG@orcl> insert into salgrade values(5,16001,50000);
JAMONG@orcl>
select
e.employee_id,
e.salary,
s.grade
from employees e, salgrade s
where e.salary between s.losal and s.hisal;
JAMONG@orcl> @xplan
๊ธ์ฌ๋ณ ๋ฑ๊ธ์ ๋๋๋ ํ ์ด๋ธ salgrade๋ฅผ ์์ฑํ๊ณ ์ง์์ ๋ฑ๊ธ์ ๊ฐ์ด ์ถ๋ ฅํ๋ non equi join ์ฟผ๋ฆฌ๋ฅผ ์คํํด๋ดค์ต๋๋ค. ์ ํ ์ด๋ธ์ ์ ๋ ฌํ๊ณ sort merge join์ ์ตํฐ๋ง์ด์ ๊ฐ ํํ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์กฐ์ธ ์กฐ๊ฑด์ ๋ง๋ ๋ฒ์์ ๋ํด ํํฐํ Inner table์ ๊ฐ๊ฐ ์ก๋ ฌ๋ ์ํ๋ก Outer Table๋ก๋ถํฐ ์์ฐจ์ ์ผ๋ก ์ฝ์ด non equi join์ ํ๋๋ฐ ์ ๋ฆฌํ ์ ์์ต๋๋ค.
ํน์ง
- ์กฐ์ธ ์นผ๋ผ์ผ๋ก ์ ๋ ฌ ํ ์กฐ์ธ ์ํ
- ์ค์์์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ๊ฒ๊ณผ ๋น์ท
- ์ ๋ ฌํ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๊ฒฝ์ฐ ๋ถ๋ด์ด ๊ฐ์ฅ ํฐ ์กฐ์ธ ๋ฐฉ๋ฒ
- ๋ ํ ์ด๋ธ ๊ฐ๋ณ์ ์ผ๋ก ์ฝ๊ณ ์กฐ์ธ
- Outer Table์ ์ธ๋ฑ์ค๊ฐ ์์ ๊ฒฝ์ฐ ์ฌ์ฉ
- Outer Table์ด ์ ๋ ฌ๋์ด ์์ ๋ ์ฌ์ฉ
- Non equi join ์ฌ์ฉ ์ ์ฌ์ฉ
3. Hash Join
Hash Join์ Hash Table์ ์์ฑํ์ฌ Hash Function์ ์ํ ํ์์ ํ์ฌ ์กฐ์ธํฉ๋๋ค. ์ฃผ๋ก ๋์ฉ๋์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ๋ ์ฌ์ฉ๋๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก Nested Loop Join์ด๋ Sorted Merge Join๋ณด๋ค ๋น ๋ฅด๋ค๊ณ ํฉ๋๋ค. ์๊ณ ๋ฆฌ์ฆ์์ ์๊ฐ ๋ณต์ก๋์ ๊ฐ๋ ์ผ๋ก ๋ดค์ ๋๋ Hash Function์ ์ฌ์ฉํ๊ฒ ๋๋ฉด O(1)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ๊ฒ๋๋๊น ๋น ๋ฅผ์ ๋ฐ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ง๋ง, ํด์ ์ถฉ๋์ ๋ฐฉ์ง๋ ํด์ ์ฒด์ธ์ ํฌ๊ธฐ๊ฐ ์ปค์ง๋ ๊ฒ์ ๋ง๊ธฐ ์ํด ์ค๋ณต๋๋ ๋ฐ์ดํฐ๊ฐ ์ ์ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋์ดํ๊ณ Hash Table์ ์์ฑํ๋๋ฐ Hash Area์ ์ถฉ๋ถํ ๋ด๊ธธ ์ ๋๋ก ๋ฐ์ดํฐ ์์ด ์์์ผํฉ๋๋ค.
์์
JAMONG@orcl>
select /*+use_hash(d,e)*/
d.department_id,
d.department_name,
e.last_name,
e.salary
from departments d, employees e
where d.department_id = e.department_id;
JAMONG@orcl> @xplan
ํํธ๋ฅผ ์ฌ์ฉํด์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ดค์ต๋๋ค. Hash Join ์ํ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ Hash Table์ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. Hash Join์ด ๋น ๋ฅด๋ค๊ณ ํ๋ ์ด์ ๋ํ PGA์์ญ์ ์ฌ์ฉํ์ฌ Latch๋ฅผ ํ๋ ๊ณผ์ ์ด ์์ด ๋น ๋ฅด๊ฒ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
ํน์ง
- ๋ ์งํฉ ์ค ํฌ๊ธฐ๊ฐ ์์ ์งํฉ์ Outer Table๋ก ๊ฒฐ์
- Outer Table์ด Hash Area์ ๋ด๊ธธ ์ ๋๋ก ์ถฉ๋ถํ ์์ ๋ ์ฌ์ฉ
- Outer Table์ ํด์ ํค ์นผ๋ผ์ ์ค๋ณต๊ฐ์ด ๊ฑฐ์ ์์ ๋ ์ฌ์ฉ
- ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ธ์ ์ฌ์ฉ
- ์๋์ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ธํ ๋ ์คํ๋ ค ๋ถํ์ํ I/O๊ฐ ์ฆ๊ฐํ ์ ์์
- Equi Join์์๋ง ๊ฐ๋ฅ
- ์กฐ์ธ ์นผ๋ผ์ ์ ๋นํ ์ธ๋ฑ์ค๊ฐ ์๋๋ฐ Nested Loop Join์ด ๋นํจ์จ ์ ์ผ ๋ ์ฌ์ฉ
- Nested Loop Join์์ ์กฐ์ธ ์นผ๋ผ์ ์ธ๋ฑ์ค๊ฐ ์๋๋ผ๋ Random Access ๋ถํ๊ฐ ์ฌํ ๋ ์ฌ์ฉ
- Sort Merge Join ์ฌ์ฉ ์ ๋๊ฐ์ ์งํฉ์ด ๋๋ฌด ์ปท ์ ๋ ฌํ๋๋ฐ ๋ถํ๊ฐ ์ฌํ ๋ ์ฌ์ฉ
๋๊ธ