- ์ตํฐ๋ง์ด์ ๋ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ์๋ฆฝํ๋ ๋ถ๋ถ์ผ๋ก ๊ฐ์ฅ ๋ณต์กํ๋ค.
- MySQL์์๋
EXPLAIN์ด๋ผ๋ ๋ช ๋ น์ผ๋ก ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ํ์ธํ ์ ์๋ค. (์๋นํ ๋ง์ ์ ๋ณด๊ฐ ์ถ๋ ฅ๋๋ค.)
- MySQL์์ ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ ๊ณผ์ ์ ์๋ ์ธ ๋จ๊ณ์ด๋ค.
- SQL ํ์ฑ
- ์ฌ์ฉ์๋ก๋ถํฐ ์์ฒญ๋ SQL ๋ฌธ์ฅ์ ์๊ฒ ์ชผ๊ฐ์ MySQL ์๋ฒ๊ฐ ์ดํดํ ์ ์๋ ์์ค์ผ๋ก ๋ถ๋ฆฌํ๋ค.
- SQL ํ์๋ผ๋ ๋ชจ๋๋ก SQL ๋ฌธ์ฅ์ ํ์ฑํ๋ค.
- ์ด ๋จ๊ณ๋ฅผ ํตํด SQL ํ์ค ํธ๋ฆฌ๊ฐ ๋ง๋ค์ด์ง๊ณ ํ์ค ํธ๋ฆฌ๋ฅผ ํตํด ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ค.
- ์ต์ ํ ๋ฐ ์คํ ๊ณํ ์๋ฆฝ
- SQL์ ํ์ฑ ์ ๋ณด๋ฅผ ํ์ธํ๋ฉด์ ์ด๋ค ํ ์ด๋ธ๋ถํฐ ์ฝ๊ณ ์ด๋ค ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ํ ์ด๋ธ์ ์ฝ์์ง ๊ฒฐ์ ํ๋ค.
- SQL ํ์ค ํธ๋ฆฌ๋ฅผ ์ฐธ์กฐํด ์์ ์ ์ํํ๋ค.
- ์คํ ๊ณํ๋๋ก ์์
์ํ
- ๋ ๋ฒ์งธ ๋จ๊ณ์์ ๊ฒฐ์ ๋ ํ ์ด๋ธ์ ์ฝ๊ธฐ ์์๋ ์ ํ๋ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ์คํ ๋ฆฌ์ง ์์ง์ผ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค.
- 2๋ฒ์งธ ๋จ๊ณ์ธ "์ต์ ํ ๋ฐ ์คํ ๊ณํ ์๋ฆฝ"์ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์์ ๋ง๋ค์ด์ง SQL ํ์ค ํธ๋ฆฌ๋ฅผ ์ฐธ์กฐํ๋ฉด์ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ ์ฒ๋ฆฌํ๋ค.
- ๋ถํ์ํ ์กฐ๊ฑด ์ ๊ฑฐ ๋ฐ ๋ณต์กํ ์ฐ์ฐ์ ๋จ์ํ
- ์ฌ๋ฌ ํ ์ด๋ธ์ ์กฐ์ธ์ด ์๋ ๊ฒฝ์ฐ ์ด๋ค ์์๋ก ํ ์ด๋ธ์ ์ฝ์์ง ๊ฒฐ์
- ๊ฐ ํ ์ด๋ธ์ ์ฌ์ฉ๋ ์กฐ๊ฑด๊ณผ ์ธ๋ฑ์ค ํต๊ณ ์ ๋ณด๋ฅผ ์ด์ฉํด ์ฌ์ฉํ ์ธ๋ฑ์ค๋ฅผ ๊ฒฐ์
- ๊ฐ์ ธ์จ ๋ ์ฝ๋๋ค์ ์์ ํ ์ด๋ธ์ ๋ฃ๊ณ ๋ค์ ํ ๋ฒ ๊ฐ๊ณตํด์ผ ํ๋์ง ๊ฒฐ์
- ์ฒซ ๋ฒ์งธ ๋จ๊ณ์ ๋ ๋ฒ์งธ ๋จ๊ณ๋ ๊ฑฐ์ MySQL ์์ง์์ ์ฒ๋ฆฌํ๋ฉฐ, ์ธ ๋ฒ์งธ ๋จ๊ณ๋ MySQL ์์ง๊ณผ ์คํ ๋ฆฌ์ง ์์ง์ด ๋์์ ์ฐธ์ฌํด์ ์ฒ๋ฆฌํ๋ค.
- ๋ ๋ฒ์งธ ๋จ๊ณ๋ ์ตํฐ๋ง์ด์ ๊ฐ ์ฒ๋ฆฌ
<br/ >
- ์ตํฐ๋ง์ด์ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๋ ์ญํ
- ๋๋ถ๋ถ์ DBMS์์๋
๋น์ฉ ๊ธฐ๋ฐ ์ต์ ํ Cost-Based Optimizer, CBO๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค. - ์์ ์ ์ค๋ผํด์์ ๋ง์ด ์ฌ์ฉํ๋
๊ท์น ๊ธฐ๋ฐ ์ต์ ํ Rule-Based Optimizer๋ฐฉ๋ฒ๋ ์๋ค.
- ์ฟผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ฌ๋ฌ ๊ฐ์ง ๊ฐ๋ฅํ ๋ฐฉ๋ฒ์ ๋ง๋ค๊ณ , ๊ฐ ๋จ์ ์์ ์ ๋น์ฉ ์ ๋ณด์ ๋์ ํ ์ด๋ธ์ ์์ธก๋ ํต๊ณ ์ ๋ณด๋ฅผ ์ด์ฉํด ์คํ ๊ณํ๋ณ๋ก ๋น์ฉ์ ์ฐ์ถํ๋ค.
- ์ด๋ ๊ฒ ์ฐ์ถ๋ ์คํ ๋ฐฉ๋ฒ ๋ณ๋ก ๋น์ฉ์ด ์ต์๋ก ์์๋๋ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ฌ์ฉํด ์ต์ข ์ ์ผ๋ก ์ฟผ๋ฆฌ ์คํ
- ์ด์ ๊ฑฐ์ ์ฌ์ฉ๋์ง ์๋ ๋ฐฉ๋ฒ
- ์ตํฐ๋ง์ด์ ์ ๋ด์ฅ๋ ์ฐ์ ์์์ ๋ฐ๋ผ ์คํ ๊ณํ์ ์๋ฆฝํ๋ ๋ฐฉ์
- ํต๊ณ ์ ๋ณด(ํ ์ด๋ธ์ ๋ ์ฝ๋ ๊ฑด์, ์นผ๋ผ๊ฐ์ ๋ถํฌ๋)๋ฅผ ์กฐ์ฌํ์ง ์๊ณ ์คํ ๊ณํ์ด ์๋ฆฝ๋๊ธฐ ๋๋ฌธ์ ๊ฐ์ ์ฟผ๋ฆฌ์ ๋ํด์ ๊ฑฐ์ ํญ์ ๊ฐ์ ๋ฐฉ๋ฒ ์คํ ๋ฐฉ๋ฒ์ ๋ง๋ค์ด๋ธ๋ค.
<br/ >
- ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๋ ฌ ๋ฐ ๊ทธ๋ฃจํ ๋ฑ์ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ๊ฐ๊ณต ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์๋ค.
- ํ์ง๋ง ๊ฒฐ๊ณผ๋ฌผ์ ๋์ผํ๋๋ผ๋ RDBMS๋ณ๋ก ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ด ๋ด๋ ๊ณผ์ ์ ์ฒ์ฐจ๋ง๋ณ์ด๋ค.
- ์ตํฐ๋ง์ด์ ๋ ์๋์ ๊ฐ์ ์กฐ๊ฑด์ผ ๋ ์ฃผ๋ก ํ ํ
์ด๋ธ ์ค์บ์ ์ ํํ๋ค.
- ํ ์ด๋ธ์ ๋ ์ฝ๋ ๊ฑด์๊ฐ ๋๋ฌด ์์์ ์ธ๋ฑ์ค๋ฅผ ํตํด ์ฝ๋ ๊ฒ๋ณด๋ค ํ ํ ์ด๋ธ ์ค์บ์ ํ๋ ํธ์ด ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ (์ผ๋ฐ์ ์ผ๋ก ํ ์ด๋ธ์ด ํ์ด์ง 1๊ฐ๋ก ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ)
- WHERE ์ ์ด๋ ON ์ ์ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ ์ ์๋ ์ ์ ํ ์กฐ๊ฑด์ด ์๋ ๊ฒฝ์ฐ
- ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ์ ์ฌ์ฉํ ์ ์๋ ์ฟผ๋ฆฌ๋ผ๊ณ ํ๋๋ผ๋ ์ตํฐ๋ง์ด์ ๊ฐ ํ๋จํ ์กฐ๊ฑด ์ผ์น ๋ ์ฝ๋ ๊ฑด์๊ฐ ๋๋ฌด ๋ง์ ๊ฒฝ์ฐ (์ธ๋ฑ์ค์ B-Tree๋ฅผ ์ํ๋งํด์ ์กฐ์ฌํ ํต๊ณ ์ ๋ณด ๊ธฐ์ค)
- ๋๋ถ๋ถ์ DBMS๋ ํ ํ
์ด๋ธ ์ค์บ์ ์คํํ ๋ ํ๊บผ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ ๋ธ๋ก์ด๋ ํ์ด์ง๋ฅผ ์ฝ์ด์ค๋ ๊ธฐ๋ฅ์ ๋ด์ฅํ๊ณ ์๋ค.
- ํ์ง๋ง MySQL์๋ ํ ํ ์ด๋ธ ์ค์บ์ ์คํํ ๋ ํ๊บผ๋ฒ์ ๋ช ๊ฐ์ฉ ํ์ด์ง๋ฅผ ์ฝ์ด์ฌ์ง ์ค์ ํ๋ ์์คํ ๋ณ์๋ ์๋ค.
- ๊ทธ๋์ ๋ง์ ์ฌ๋๋ค์ด MySQL์ ํ ํ ์ด๋ธ ์ค์บ์ ์คํํ ๋ ๋์คํฌ๋ก๋ถํฐ ํ์ด์ง๋ฅผ ํ๋์ฉ ์ฝ์ด ์จ๋ค๊ณ ์๊ฐํ์ง๋ง ๊ทธ๊ฒ์ ์ฐฉ๊ฐ์ด๋ค.
- MyISAM์์ ํ ํ
์ด๋ธ ์ค์บ์ ํ ๋๋ ๋์คํฌ๋ก๋ถํฐ ํ์ด์ง๋ฅผ ํ๋์ฉ ์ฝ์ด์ค์ง๋ง InnoDB์ ์๋ ๋ฐฉ์์ ์ฝ๊ฐ ๋ค๋ฅด๋ค.
- InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ํน์ ํ
์ด๋ธ์ ์ฐ์๋ ๋ฐ์ดํฐ ํ์ด์ง๊ฐ ์ฝํ๋ฉด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์ ์ํด
๋ฆฌ๋ ์ดํค๋ Read ahead์์ ์ด ์๋์ผ๋ก ์์๋๋ค. - ์ฌ๊ธฐ์
๋ฆฌ๋ ์ดํค๋๋ ์ด๋ค ์์ญ์์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ก ํ์ํด์ง๋ฆฌ๋ผ๋ ๊ฒ์ ์์ธกํด์ ์์ฒญ์ด ์ค๊ธฐ ์ ์ ๋ฏธ๋ฆฌ ๋์คํฌ์์ ์ฝ์ด InnoDB์ ๋ฒํผ ํ์ ๊ฐ์ ธ๋ค ๋๋ ๊ฒ์ ์๋ฏธํ๋ค. - ์ฆ, ํ ํ
์ด๋ธ ์ค์บ์ด ์คํ๋๋ฉด ์ฒ์ ๋ช ๊ฐ์ ๋ฐ์ดํฐ ํ์ด์ง๋
ํฌ๊ทธ๋ผ์ด๋ ์ค๋ ๋ (Foreground thread, ํด๋ผ์ด์ธํธ ์ค๋ ๋)๊ฐ ํ์ด์ง ์ฝ๊ธฐ๋ฅผ ์คํํ์ง๋ง, ํน์ ์์ ๋ถํฐ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๋ก ๋๊ธด๋ค. - ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๊ฐ ์ฝ๊ธฐ๋ฅผ ๋๊ฒจ๋ฐ์ผ๋ฉด ํ ๋ฒ์ 4๊ฐ ๋๋ 8๊ฐ์ฉ ํ์ด์ง๋ฅผ ์ฝ์ผ๋ฉด์ ๊ณ์ ๊ทธ ์๋ฅผ ์ฆ๊ฐ์ํจ๋ค. ์ด ๋ ํ ๋ฒ์ ์ต๋ 64๊ฐ์ ๋ฐ์ดํฐ ํ์ด์ง๊น์ง ์ฝ์ด์ ๋ฒํผ ํ์ ์ ์ฅํด๋๋ค.
- ํฌ๊ทธ๋ผ์ด๋ ์ค๋ ๋๋ ๋ฒํผ ํ์ ์ค๋น๋ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ๋ค ์ฌ์ฉํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ์ฟผ๋ฆฌ๊ฐ ์๋นํ ๋นจ๋ฆฌ ์ฒ๋ฆฌ๋๋ ๊ฒ์ด๋ค.
- InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ํน์ ํ
์ด๋ธ์ ์ฐ์๋ ๋ฐ์ดํฐ ํ์ด์ง๊ฐ ์ฝํ๋ฉด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์ ์ํด
innodb_read_ahead_threshold๋ผ๋ ์์คํ ๋ณ์๋ฅผ ์ด์ฉํด ๋ฆฌ๋ ์ดํค๋๋ฅผ ์ธ์ ์์ํ ์ง ์๊ณ๊ฐ์ ์ ํ ์ ์๋ค.- ์ผ๋ฐ์ ์ผ๋ก ๋ํดํธ ์ค์ ์ผ๋ก๋ ์ถฉ๋ถํ์ง๋ง ๋ฐ์ดํฐ ์จ์ดํ์ฐ์ค์ฉ์ผ๋ก MySQL์ ์ฌ์ฉํ๋ค๋ฉด ์ด ์ต์ ์ ๋ ๋ฎ์ ๊ฐ์ผ๋ก ์ค์ ํด์ ๋ ๋นจ๋ฆฌ ๋ฆฌ๋ ์ดํค๋๊ฐ ์์๋๊ฒ ์ ๋ํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด๋ค.
- ๋ฆฌ๋ ์ดํค๋๋ ํ ํ ์ด๋ธ ์ค์บ์์๋ง ์ฌ์ฉ๋๋ ๊ฒ์ด ์๋๋ผ ํ ์ธ๋ฑ์ค ์ค์บ์์๋ ๋์ผํ๊ฒ ์ฌ์ฉ๋๋ค.
- MySQL 8.0๋ถํฐ ์ฒ์์ผ๋ก ์ฟผ๋ฆฌ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ก๋ค.
- ์ฌ๊ธฐ์ ๋งํ๋ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ ํ๋์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์์ ์ ๋๋์ด ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
- ์ฌ๋ฌ ๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ๋์์ ์ฒ๋ฆฌํ๋ ๊ฒ์ MySQL๊ฐ ์ฒ์ ๋ง๋ค์ด์ง ๋๋ถํฐ ๊ฐ๋ฅํ๋ค.
innodb_parallel_read_threads๋ผ๋ ์์คํ ๋ณ์๋ฅผ ์ด์ฉํด ํ๋์ ์ฟผ๋ฆฌ๋ฅผ ์ต๋ ๋ช ๊ฐ์ ์ค๋ ๋๋ฅผ ์ด์ฉํด์ ์ฒ๋ฆฌํ ์ง๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.- ํ์ง๋ง ์์ง MySQL ์๋ฒ์์๋ ์ฟผ๋ฆฌ๋ฅผ ์ฌ๋ฌ ๊ฐ์ ์ค๋ ๋๋ฅผ ์ด์ฉํด ๋ณ๋ด๋ก ์ฒ๋ฆฌํ๊ฒ ํ๋ ํํธ๋ ์ต์ ์ ์๋ค.
mysql> SET SESSION innodb_parallel_read_threads=1;
mysql> SELECT COUNT(*) FROM salaries;
1 row in set (0.81 sec)
# ์ด ์๊ฐ๋ถํฐ ์ฟผ๋ฆฌ๊ฐ ๊ฐ์ ๋์ง ์๋๋ค.
mysql> SET SESSION innodb_parallel_read_threads=2;
mysql> SELECT COUNT(*) FROM salaries;
1 row in set (0.19 sec)
mysql> SET SESSION innodb_parallel_read_threads=4;
mysql> SELECT COUNT(*) FROM salaries;
1 row in set (0.19 sec)
mysql> SET SESSION innodb_parallel_read_threads=8;
mysql> SELECT COUNT(*) FROM salaries;
1 row in set (0.19 sec)- ๋ณ๋ ฌ ์ฒ๋ฆฌ์ฉ ์ค๋ ๋ ๊ฐ์๊ฐ ๋์ด๋ ์๋ก ์ฟผ๋ฆฌ ์ฒ๋ฆฌ์ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ด ์ค์ด๋ ๋ค๊ณ ํ๋, ์๋ฒ์ ์ฅ์ฐฉ๋ CPI์ ์ฝ์ด ๊ฐ์๋ฅผ ๋์ด๊ฐ๋ฉด ์คํ๋ ค ์ฑ๋ฅ์ด ์ ์ข์์ง๋ค๊ณ ํ๋ค.
- ์ ๋ ฌ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์ฟผ๋ฆฌ๊ฐ ์คํ๋ ๋ Filesort๋ผ๋ ๋ณ๋์ ์ฒ๋ฆฌ๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋๋ ์ ์๋ค.
| ์ฅ์ | ๋จ์ | |
| ์ธ๋ฑ์ค ์ด์ฉ | INSERT, UPDATE, DELETE ์ฟผ๋ฆฌ๊ฐ ์คํ๋ ๋ ์ด๋ฏธ ์ธ๋ฑ์ค๊ฐ ์ ๋ ฌ๋์ด ์์ด์ ์์๋๋ก ์ฝ๊ธฐ๋ง ํ๋ฉด ๋๋ฏ๋ก ๋งค์ฐ ๋น ๋ฅด๋ค. | INSERT, UPDATE, DELETE ์์ ์ ๋ถ๊ฐ์ ์ธ ์ธ๋ฑ์ค ์ถ๊ฐ/์ญ์ ์์ ์ด ํ์ํ๋ฏ๋ก ๋๋ฆฌ๋ค. ์ธ๋ฑ์ค ๋๋ฌธ์ ๋์คํฌ ๊ณต๊ฐ์ด ๋ ๋ง์ด ํ์ํ๋ค. ์ธ๋ฑ์ค์ ๊ฐ์๊ฐ ๋์ด๋ ์๋ก InnoDB์ ๋ฒํผ ํ์ ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ง์ด ํ์ํ๋ค. |
| Filesort ์ด์ฉ | ์ธ๋ฑ์ค๋ฅผ ์์ฑํ์ง ์์๋ ๋๋ฏ๋ก ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ ๋์ ๋จ์ ์ด ์ฅ์ ์ผ๋ก ๋ฐ๋๋ค. ์ ๋ ฌํด์ผ ํ ๋ ์ฝ๋๊ฐ ๋ง์ง ์์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ์์ Filesort๊ฐ ์ฒ๋ฆฌ๋๋ฏ๋ก ์ถฉ๋ถํ ๋น ๋ฅด๋ค. | ์ ๋ ฌ ์์ ์ด ์ฟผ๋ฆฌ ์คํ ์ ์ฒ๋ฆฌ๋๋ฏ๋ก ๋ ์ฝ๋ ๋์ ๊ฑด์๊ฐ ๋ง์์ง ์๋ก ์ฟผ๋ฆฌ์ ์๋ต ์๋๊ฐ ๋๋ฆฌ๋ค. |
- ๋ฌผ๋ก ๋ ์ฝ๋๋ฅผ ์ ๋ ฌํ๊ธฐ ์ํด ํญ์ "Filesort"๋ผ๋ ์ ๋ ฌ ์์ ์ ๊ฑฐ์ณ์ผ ํ๋ ๊ฒ์ ์๋๋ค. ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ ์ ๋ ฌ๋ ๊ฐ๋ฅํ๋ค.
- ํ์ง๋ง ์๋์ ๊ฐ์ ์ด์ ๋ก ๋ชจ๋ ์ ๋ ฌ์ ์ธ๋ฑ์ค๋ก ์ฒ๋ฆฌํด ํ๋ํ๊ธฐ๋ ๋ถ๊ฐ๋ฅํ๋ค.
- ์ ๋ ฌ ๊ธฐ์ค์ด ๋๋ฌด ๋ง์์ ์๊ฑด๋ณ๋ก ๋ชจ๋ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ ๋
- GROUP BY์ ๊ฒฐ๊ณผ ๋๋ DISTINCT ๊ฐ์ ์ฒ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ ฌํด์ผํ ๋
- UNION์ ๊ฒฐ๊ณผ์ ๊ฐ์ด ์์ ํ ์ด๋ธ์ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ ๋ ฌํด์ผํ ๋
- ๋๋คํ๊ฒ ๊ฒฐ๊ณผ ๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์์ผํ ๋
- ๋ณ๋์ ์ ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋์ง๋ ์คํ ๊ณํ์ Extra ์นผ๋ผ์ "Using filesort" ๋ฉ์์ง๊ฐ ํ์๋๋์ง ์ฌ๋ถ๋ก ํ๋จํ ์ ์๋ค.
- MySQL์์๋ ์ ๋ ฌ์ ์ํํ๊ธฐ ์ํด ๋ณ๋์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ ๋น๋ฐ์ ์ฌ์ฉํ๋๋ฐ ์ด ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์
์ํธ ๋ฒํผ Sort buffer๋ผ๊ณ ํ๋ค. - ์ํธ ๋ฒํผ๋ ์ ๋ ฌ์ด ํ์ํ ๊ฒฝ์ฐ์๋ง ํ ๋น๋๋ฉฐ, ๋ฒํผ์ ํฌ๊ธฐ๋ ์ ๋ ฌํด์ผ ํ ๋ ์ฝ๋์ ํฌ๊ธฐ์ ๋ฐ๋ผ ๊ฐ๋ณ์ ์ผ๋ก ์ฆ๊ฐํ์ง๋ง ์ต๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์ํธ ๋ฒํผ์ ๊ณต๊ฐ์
sort_buffer_size๋ผ๋ ์์คํ ๋ณ์๋ก ์ค์ ํ ์ ์๋ค.- ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฟผ๋ฆฌ ์คํ์ด ์๋ฃ๋๋ฉด ๋ฐ๋ก ๋ฐ๋ฉ๋๋ค.
- ๊ทธ๋ฐ๋ฐ ์ ๋ ฌ์ด ์ ๋ฌธ์ ๊ฐ ๋ ๊น?
- ์ ๋ ฌํ ๋ ์ฝ๋๊ฐ ์์ฃผ ์๋์ด์ด์ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋ ์ํธ ๋ฒํผ๋ง์ผ๋ก ์ ๋ ฌํ ์ ์๋ค๋ฉด ์์ฃผ ๋น ๋ฅด๊ฒ ์ ๋ ฌ์ด ์ฒ๋ฆฌ๋ ๊ฒ์ด๋ค.
- ํ์ง๋ง ์ ๋ ฌํด์ผ ํ ๋ ์ฝ๋์ ๊ฑด์๊ฐ ์ํธ ๋ฒํผ๋ก ํ ๋น๋ ๊ณต๊ฐ๋ณด๋ค ํฌ๋ค๋ฉด ์ด๋จ๊น?
- ์ ๋ ฌํด์ผ ํ ๋ ์ฝ๋์ ๊ฑด์๊ฐ ์ํธ ๋ฒํผ๋ณด๋ค ๋ง์์ง๋ฉด ๋ ์ฝ๋๋ฅผ ์ฌ๋ฌ ์กฐ๊ฐ์ผ๋ก ๋๋ ์ฒ๋ฆฌํ๋ค.
- ์ํธ ๋ฒํผ์์ ์ ๋ ฌ์ ์ํํ๊ณ ๋์คํฌ์ ์์๋ก ์ ์ฅํด๋๋ค. ์ด๊ฒ์ ๋ฐ๋ณตํ๋ค.
- ๊ฐ ๋ฒํผ์ ํฌ๊ธฐ๋งํผ ์ ๋ ฌ๋ ๋ ์ฝ๋๋ฅผ ๋ค์ ๋ณํฉํ๋ฉด์ ์ ๋ ฌ์ ์ํํด์ผ ํ๋ค.
Multi-Merge ๋ฉํฐ ๋จธ์ง - ์ํ๋ ๋ฉํฐ ๋จธ์ง ํ์๋
Sort_merge_passes๋ผ๋ ์ํ ๋ณ์์ ๋์ ํด์ ์ง๊ณ๋๋ค.
- ์ด ์์
๋ค์ด ๋ชจ๋ ๋์คํฌ์ ์ฐ๊ธฐ์ ์ฝ๊ธฐ๋ฅผ ์ ๋ฐํ๋ฉฐ, ๋ ์ฝ๋ ๊ฑด์๊ฐ ๋ง์์๋ก ์ด ๋ฐ๋ณต ์์
์ ํ์๊ฐ ๋ง์์ง๋ค.
- ์ํธ ๋ฒํผ๋ฅผ ํฌ๊ฒ ์ค์ ํ๋ฉด ๋์คํฌ๋ฅผ ์ฌ์ฉํ์ง ์์์ ๋ ๋นจ๋ผ์ง ๊ฒ์ผ๋ก ์๊ฐํ ์๋ ์์ง๋ง, ์ค์ ๋ฒค์น๋งํฌ ๊ฒฐ๊ณผ๋ก๋ ํฐ ์ฐจ์ด๋ฅผ ๋ณด์ด์ง ์์๋ค.
- 256KB ~ 8MB์์ ์ต์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์.
- ๋๋ฌด ํฐ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์ฑ๋ฅ์ ๋จ์ด๋จ๋ฆฐ๋ค.
- ํ์์ ์ํ๋ฉด ์ ๋นํ ์ํธ๋ฒํผ์ ํฌ๊ธฐ๋ 56KB์์ 1MB ๋ฏธ๋ง ์ด๋ผ๊ณ ํ๋ค.
- ์ํธ ๋ฒํผ๋ ์ฌ๋ฌ ํด๋ผ์ด์ธํธ๊ฐ ๊ณต์ ํด์ ์ฌ์ฉํ ์ ์๋ ์์ญ์ด ์๋๋ค.
- ์ปค๋ฅ์ ์ด ๋ง์ผ๋ฉด ๋ง์์๋ก, ์ ๋ ฌ ์์ ์ด ๋ง์ผ๋ฉด ๋ง์์๋ก ์ํธ ๋ฒํผ๋ก ์๋น๋๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ด ์ปค์ง์ ์๋ฏธํ๋ค.
- ๋ ์ฝ๋ ์ ์ฒด๋ฅผ ๋ฒํผ์ ๋ด์์ง, ์ ๋ ฌ ๊ธฐ์ค ์นผ๋ผ๋ง ์ํธ ๋ฒํผ์ ๋ด์์ง์ ๋ฐ๋ผ
์ฑ๊ธ ํจ์ค Single-Pass์ํฌ ํจ์ค Two-Pass2๊ฐ์ง๋ก ๋ชจ๋๋ฅผ ๋๋ ์ ์๋ค. - ์ ๋ ฌ์ ์ํํ๋ ์ฟผ๋ฆฌ๊ฐ ์ด๋ค ์ ๋ ฌ ๋ชจ๋๋ฅผ ์ฌ์ฉํ๋์ง๋ ์๋์ ๊ฐ์ด ์ตํฐ๋ง์ด์ ํธ๋ ์ด์ค ๊ธฐ๋ฅ์ผ๋ก ํ์ธํ ์ ์๋ค.
mysql> SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
mysql> SET OPTIMIZER_TRACE_MAX_MEM_SIZE=1000000;- ์ฟผ๋ฆฌ๋ฅผ ์คํํด๋ณด์.
mysql> SELECT * FROM employees ORDER BY last_name LIMIT 100000, 1;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 418804 | 1958-01-06 | Jacopo | Gyimothy | F | 1997-06-20 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.21 sec)- ๊ทธ๋ฆฌ๊ณ ํธ๋ ์ด์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ฉด ์ตํฐ๋ง์ด์ ์ ํธ๋ ์ด์ค ๋ด์ฉ์ ํ์ธํ ์ ์๋ค.
mysql> SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE \G
*************************** 1. row ***************************
QUERY: SELECT * FROM employees ORDER BY last_name LIMIT 100000, 1
TRACE: {
"steps": [
{
"join_preparation": {
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `employees`.`emp_no` AS `emp_no`,`employees`.`birth_date` AS `birth_date`,`employees`.`first_name` AS `first_name`,`employees`.`last_name` AS `last_name`,`employees`.`gender` AS `gender`,`employees`.`hire_date` AS `hire_date` from `employees` order by `employees`.`last_name` limit 100000,1"
}
] /* steps */
} /* join_preparation */
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
"substitute_generated_columns": {
} /* substitute_generated_columns */
},
{
"table_dependencies": [
{
"table": "`employees`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
},
{
"rows_estimation": [
{
"table": "`employees`",
"table_scan": {
"rows": 300252,
"cost": 922.709
} /* table_scan */
}
] /* rows_estimation */
},
{
"considered_execution_plans": [
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`employees`",
"best_access_path": {
"considered_access_paths": [
{
"rows_to_scan": 300252,
"access_type": "scan",
"resulting_rows": 300252,
"cost": 30947.9,
"chosen": true
}
] /* considered_access_paths */
} /* best_access_path */,
"condition_filtering_pct": 100,
"rows_for_plan": 300252,
"cost_for_plan": 30947.9,
"chosen": true
}
] /* considered_execution_plans */
},
{
"attaching_conditions_to_tables": {
"original_condition": null,
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [
{
"table": "`employees`",
"attached": null
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
},
{
"optimizing_distinct_group_by_order_by": {
"simplifying_order_by": {
"original_clause": "`employees`.`last_name`",
"items": [
{
"item": "`employees`.`last_name`"
}
] /* items */,
"resulting_clause_is_simple": true,
"resulting_clause": "`employees`.`last_name`"
} /* simplifying_order_by */
} /* optimizing_distinct_group_by_order_by */
},
{
"finalizing_table_conditions": [
] /* finalizing_table_conditions */
},
{
"refine_plan": [
{
"table": "`employees`"
}
] /* refine_plan */
},
{
"considering_tmp_tables": [
{
"adding_sort_to_table": "employees"
} /* filesort */
] /* considering_tmp_tables */
}
] /* steps */
} /* join_optimization */
},
{
"join_execution": {
"select#": 1,
"steps": [
{
"sorting_table": "employees",
"filesort_information": [
{
"direction": "asc",
"expression": "`employees`.`last_name`"
}
] /* filesort_information */,
"filesort_priority_queue_optimization": {
"limit": 100001
} /* filesort_priority_queue_optimization */,
"filesort_execution": [
] /* filesort_execution */,
"filesort_summary": {
"memory_available": 262144,
"key_size": 32,
"row_size": 169,
"max_rows_per_buffer": 1551,
"num_rows_estimate": 300252,
"num_rows_found": 300024,
"num_initial_chunks_spilled_to_disk": 82,
"peak_memory_used": 262144,
"sort_algorithm": "std::stable_sort",
"sort_mode": "<fixed_sort_key, packed_additional_fields>"
} /* filesort_summary */
}
] /* steps */
} /* join_execution */
}
] /* steps */
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
INSUFFICIENT_PRIVILEGES: 0
1 row in set (0.00 sec)- "filesort_summary" ์น์ ์ "sort_algorithm" ํ๋์ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ์ด ํ์๋๋ค.
"filesort_summary": {
"memory_available": 262144,
"key_size": 32,
"row_size": 169,
"max_rows_per_buffer": 1551,
"num_rows_estimate": 300252,
"num_rows_found": 300024,
"num_initial_chunks_spilled_to_disk": 82,
"peak_memory_used": 262144,
"sort_algorithm": "std::stable_sort",
"sort_mode": "<fixed_sort_key, packed_additional_fields>"
} /* filesort_summary */- ๋ํ "sort_mode" ํ๋์๋ "<fixed_sort_key, packed_additional_fields>"๊ฐ ํ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ ํํ๋ MySQL ์๋ฒ์ ์ ๋ ฌ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ด 3๊ฐ์ง๊ฐ ์๋ค.
<sort_key, rowid>: ์ ๋ ฌ ํค์ ๋ ์ฝ๋์ ๋ก์ฐ ์์ด๋(Row ID)๋ง ๊ฐ์ ธ์์ ์ ๋ ฌํ๋ ๋ฐฉ์<sort_key, additional_fields>: ์ ๋ ฌ ํค์ ๋ ์ฝ๋ ์ ์ฒด๋ฅผ ๊ฐ์ ธ์์ ์ ๋ ฌํ๋ ๋ฐฉ์. ๋ ์ฝ๋์ ์นผ๋ผ๋ค์ ๊ณ ์ ์ฌ์ด์ฆ๋ก ๋ฉ๋ชจ๋ฆฌ ์ ์ฅ<sort_key, packed_additional_fields>: ์ ๋ ฌ ํค์ ๋ ์ฝ๋ ์ ์ฒด๋ฅผ ๊ฐ์ ธ์์ ์ ๋ ฌํ๋ ๋ฐฉ์. ๋ ์ฝ๋์ ์นผ๋ผ๋ค์ ๊ฐ๋ณ ์ฌ์ด์ฆ๋ก ๋ฉ๋ชจ๋ฆฌ ์ ์ฅ
- ์ฌ๊ธฐ์ ์ฒซ ๋ฒ์งธ ๋ฐฉ์์ "ํฌ ํจ์ค" ์ ๋ ฌ ๋ฐฉ์, ๋ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ๋ฐฉ์์ "์ฑ๊ธ ํจ์ค" ์ ๋ ฌ ๋ฐฉ์์ด๋ผ ํ๋ค.
- ์ํธ ๋ฒํผ์ ์ ๋ ฌ ๊ธฐ์ค ์นผ๋ผ์ ํฌํจํด SELECT ๋์์ด ๋๋ ์นผ๋ผ ์ ๋ถ๋ฅผ ๋ด์์ ์ ๋ ฌ์ ์ํํ๋ ์ ๋ ฌ ๋ฐฉ๋ฒ์ด๋ค.
mysql> SELECT emp_no, first_name, last_name
FROM employees
ORDER BY first_name;- ํ ์ด๋ธ์ ์ฝ์ ๋ '์ ๋ ฌ์ ํ์ํ์ง ์์ ์นผ๋ผ๊น์ง ์ ๋ถ' ์ฝ์ด์ ์ํธ ๋ฒํผ์ ๋ด๊ณ ์ ๋ ฌ์ ์ํํ๋ค.
- ์ ๋ ฌ์ด ์๋ฃ๋๋ฉด ์ ๋ ฌ ๋ฒํผ์ ๋ด์ฉ์ ๊ทธ๋๋ก ํด๋ผ์ด์ธํธ๋ก ๋๊ฒจ์ค๋ค.
- ์ ๋ ฌ ๋์ ์ปฌ๋ผ๊ณผ ํ๋ผ์ด๋จธ๋ฆฌ ํค ๊ฐ๋ง ์ํธ ๋ฒํผ์ ๋ด์์ ์ ๋ ฌ์ ์ํํ๊ณ , ์ ๋ ฌ๋ ์์๋๋ก ๋ค์ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ก ํ
์ด๋ธ์ ์ฝ์ด์ค๋ ๋ฐฉ์
- ์ฑ๊ธ ํจ์ค ์ ๋ ฌ ๋ฐฉ์์ด ๋์ ๋๊ธฐ ์ด์ ๋ถํฐ ์ฌ์ฉํ๋ ๋ฐฉ์. ํ์ง๋ง MySQL 8.0์์๋ ์ฌ์ ํ ํน์ ์กฐ๊ฑด์์๋ ํฌ ํจ์ค ์ ๋ ฌ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
์ ๋ ฌ์ ํ์ํ ์นผ๋ผ+ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ง ์ฝ์ด์ ์ ๋ ฌ์ ์ํํ๊ณ , ๋๋จธ์ง ์กฐํ ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋ฐฉ์์ด๋ค.- ํ
์ด๋ธ์ 2๋ฒ ์ฝ์ด์ผ ํ๋ค๋ ์ ์์ ๋นํจ์จ์ ์ด๋ค.
- ์๋ก์ด ์ ๋ ฌ ๋ฐฉ์์ธ ์ฑ๊ธ ํจ์ค๋ ์ด๋ฐ ๋ถํฉ๋ฆฌ๊ฐ ์๋ค.
- ์ต์ ๋ฒ์ ์์๋ ์ผ๋ฐ์ ์ผ๋ก ์ฑ๊ธ ํจ์ค ์ ๋ ฌ ๋ฐฉ์์ ์ฃผ๋ก ์ฌ์ฉํ๋ค. ๋์ ์ฑ๊ธ ํจ์ค ๋ฐฉ์์ ๋ ๋ง์ ์ํธ ๋ฒํผ์ ๊ณต๊ฐ์ด ํ์ํ๋ค.
- ex) 128KB ์ ๋ ฌ ๋ฒํผ. ํฌ ํจ์ค๋ 7,000๊ฑด ๋ ์ฝ๋ ์ ๋ ฌ ๊ฐ๋ฅ, ๋ฐ๋ฉด ์ฑ๊ธ ํจ์ค๋ ์ ๋ฐ์ธ 3,500๊ฑด ์ ๋๋ฐ์ ์ ๋ ฌํ ์ ์๋ค.
- ํ์ง๋ง, ์๋์ ๊ฒฝ์ฐ MySQL์ ์ฑ๊ธ ํจ์ค ๋ฐฉ์์ ์ฌ์ฉํ์ง ๋ชปํ๊ณ ํฌ ํจ์ค ์ ๋ ฌ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
- ๋ ์ฝ๋์ ํฌ๊ธฐ๊ฐ
max_length_for_sort_data์์คํ ๋ณ์์ ์ค์ ๋ ๊ฐ๋ณด๋ค ํด ๋ - BLOB์ด๋ TEXT ํ์ ์ ์นผ๋ผ์ด SELECT ๋์์ ํฌํจ๋ ๋
- ๋ ์ฝ๋์ ํฌ๊ธฐ๊ฐ
- ์ฑ๊ธ ํจ์ค๋ ๋ ์ฝ๋์ ํฌ๊ธฐ๋ ๊ฑด์๊ฐ ์์ ๊ฒฝ์ฐ ๋น ๋ฅธ ๋ฐ๋ฉด, ํฌ ํจ์ค ๋ฐฉ์์ ๋ ์ฝ๋์ ํฌ๊ธฐ๋ ๊ฑด์๊ฐ ์๋นํ ๋ง์ ๊ฒฝ์ฐ ํจ์จ์ ์ด๋ค.
- SELECT ์ฟผ๋ฆฌ์์ ๊ผญ ํ์ํ ์นผ๋ผ๋ง ์กฐํํ์ง ์๊ณ , ๋ชจ๋ ์นผ๋ผ(*)์ ๊ฐ์ ธ์ค๋๋ก ๊ฐ๋ฐํ ๋๊ฐ ๋ง์ ๊ฒ์ด๋ค. ํ์ง๋ง ์ด๋ ์ ๋ ฌ ๋ฒํผ๋ฅผ ๋ช ๋ฐฐ์์ ๋ช์ญ ๋ฐฐ๊น์ง ๋นํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ค.
- SELECT ์ฟผ๋ฆฌ์์ ๊ผญ ํ์ํ ์นผ๋ผ๋ง ์กฐํํ๋๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ข๋ค๊ณ ๊ถ์ฅํ๋ ๊ฒ์ ๋ฐ๋ก ์ด๋ฐ ์ด์ ๋๋ฌธ์ด๋ค.
ORDER BY๊ฐ ์ฌ์ฉ๋๋ฉด ๋ฐ๋์ ์๋ 3๊ฐ์ง ์ฒ๋ฆฌ ๋ฐฉ๋ฒ ์ค ํ๋๋ก ์ ๋ ฌ์ด ์ฒ๋ฆฌ๋๋ค.
| ์ ๋ ฌ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ | ์คํ ๊ณํ์ Extra ์นผ๋ผ ๋ด์ฉ |
|---|---|
| ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ๋ ฌ | ๋ณ๋ ํ๊ธฐ ์์ |
| ์กฐ์ธ์์ ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌ | "Using filesort" ๋ฉ์์ง ํ์๋จ |
| ์กฐ์ธ์์ ์กฐ์ธ ๊ฒฐ๊ณผ๋ฅผ ์์ ํ ์ด๋ธ๋ก ์ ์ฅ ํ ์ ๋ ฌ | "Using temporary; Using filesort" ๋ฉ์์ง ํ์๋จ |
- ๋จผ์ ์ตํฐ๋ง์ด์ ๋ ์ ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ํด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋์ง ๊ฒํ ํ๋ค. ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ฉด ๋ ์ฝ๋๋ฅผ ๊ฒ์์ ์ ๋ ฌ ๋ฒํผ์ ์ ์ฅํ๋ฉด์ ์ ๋ ฌ ์ฒ๋ฆฌ(Filesort)๋ฅผ ํ๋ค.
- Filesort๋ฅผ ํ ๋ ์ตํฐ๋ง์ด์ ๋ 2๊ฐ์ง ๋ฐฉ๋ฒ ์ค ํ๋๋ฅผ ์ ํํ๋ค. (๊ฐ๋ฅํ๋ค๋ฉด ์ ์๊ฐ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.)
- ์กฐ์ธ์ด ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌํ ๋ค์ ์กฐ์ธ์ ์ํ
- ์กฐ์ธ์ด ๋๋๊ณ ์ผ์นํ๋ ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์จ ํ ์ ๋ ฌ์ ์ํ
- ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ๋ ฌ์ ์ํด์๋ ๋ฐ๋์
ORDER BY์ ๋ฉด์๋ ์นผ๋ผ์ด ์ ์ผ ๋จผ์ ์ฝ๋ ํ ์ด๋ธ์ ์ํ๊ณ ,ORDER BY์ ์์๋๋ก ์์ฑ๋ ์ธ๋ฑ์ค๊ฐ ์์ด์ผ ํ๋ค.- ๋ํ
WHERE์ ์ ์ฒซ ๋ฒ์งธ๋ก ์ฝ๋ ํ ์ด๋ธ์ ์นผ๋ผ์ ๋ํ ์กฐ๊ฑด์ด ์๋ค๋ฉด ๊ทธ ์กฐ๊ฑด๊ณผORDER BY๋ ๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ด์ผ ํ๋ค. - ๊ทธ๋ฆฌ๊ณ B-Tree ๊ณ์ด์ ์ธ๋ฑ์ค๊ฐ ์๋ ํด์ ์ธ๋ฑ์ค๋ ์ ๋ฌธ ๊ฒ์ ์ธ๋ฑ์ค ๋ฑ์์๋ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ ์ ๋ ฌ์ ์ฌ์ฉํ ์ ์๋ค.
- ์ฌ๋ฌ ํ
์ด๋ธ์ด ์กฐ์ธ๋๋ ๊ฒฝ์ฐ์๋
๋ค์คํฐ๋ ๋ฃจํ Nested-loop๋ฐฉ์์ ์กฐ์ธ์์๋ง ์ด ๋ฐฉ์์ ์ฌ์ฉํ ์ ์๋ค.
- ๋ํ
- ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ์ ๋ ฌ์ด ์ฒ๋ฆฌ๋๋ ๊ฒฝ์ฐ์๋ ์ค์ ์ธ๋ฑ์ค์ ๊ฐ์ด ์ ๋ ฌ๋ผ ์๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค์ ์์๋๋ก ์ฝ๊ธฐ๋ง ํ๋ฉด ๋๋ค.
- ์กฐ์ธ์ด ์ํ๋๋ฉด ๋ ์ฝ๋์ ๊ฑด์๊ฐ ๋ช ๋ฐฐ๋ก ๋ถ์ด๋๊ณ , ๋ ์ฝ๋ ํ๋ํ๋์ ํฌ๊ธฐ๋ ๋์ด๋๋ค.
- ๋ฐ๋ผ์ ์กฐ์ธ์ ์คํํ๊ธฐ ์ ์ ์ฒซ ๋ฒ์งธ ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ๋จผ์ ์ ๋ ฌํ ๋ค์ ์กฐ์ธ์ ์คํํ๋ ๊ฒ์ด ์ ๋ ฌ์ ์ฐจ์ ์ฑ ์ด ๋ ๊ฒ์ด๋ค.
- ์ด ๋ฐฉ๋ฒ์ผ๋ก ์ ๋ ฌ์ด ์ฒ๋ฆฌ๋๋ ค๋ฉด ์กฐ์ธ์์ ์ฒซ ๋ฒ์งธ๋ก ์ฝํ๋ ํ
์ด๋ธ(๋๋ผ์ด๋น ํ
์ด๋ธ)์ ์นผ๋ผ๋ง์ผ๋ก
ORDER BY์ ์ ์์ฑํด์ผ ํ๋ค.
- 2๊ฐ ์ด์์ ํ
์ด๋ธ์ ์กฐ์ธํด์ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ ฌํด์ผ ํ๋ค๋ฉด ์์ ํ
์ด๋ธ์ด ํ์ํ ์ ์๋ค.
- ์์ธ! ์กฐ์ธ์ ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌํ ๋๋ 2๊ฐ ์ด์์ ํ ์ด๋ธ์ด ์กฐ์ธ๋๋ฉด์ ์ ๋ ฌ์ด ์คํ๋์ง๋ง ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ์ง ์๋๋ค. (์กฐ์ธ๋๋ ํ ์ด๋ธ์ด ์ ๋ ฌ ๊ธฐ์ค์ด ์๋๊ธฐ ๋๋ฌธ์!)
- ์กฐ์ธ์ ๊ฒฐ๊ณผ๋ฅผ ์์ ํ ์ด๋ธ์ ์ ์ฅํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ ๋ ฌํ๋ ๊ณผ์ ์ ๊ฑฐ์น๋ค. ์ด ๋ฐฉ๋ฒ์ ์ ๋ ฌ์ 3๊ฐ์ง ๋ฐฉ๋ฒ ๊ฐ์ด๋ฐ ์ ๋ ฌํด์ผ ํ ๋ ์ฝ๋ ๊ฑด์๊ฐ ๊ฐ์ฅ ๋ง๊ธฐ ๋๋ฌธ์ ๊ฐ์ฅ ๋๋ฆฐ ์ ๋ ฌ ๋ฐฉ๋ฒ์ด๋ค.
- ์๋์ ๊ฐ์ด ์ ๋ ฌ ๊ธฐ์ค์ด ๋๋ผ์ด๋น ํ ์ด๋ธ์ด ์๋๋ผ ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ ์๋ค๋ฉด ์ด ์ฟผ๋ฆฌ๋ ์กฐ์ธ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ ๋ ฌํด์ผ ํ๋ฉด, ์ด ๊ฒฝ์ฐ ์์ ํ ์ด๋ธ์ ํ์ฉํ๋ค.
mysql> SELECT *
FROM employees e, salaries s
WHERE s.emp_no=e.emp_no
AND e.emp_no BETWEEN 100002 AND 100010
ORDER BY s.salary;- ์ ์ฟผ๋ฆฌ์ ์คํ๊ณํ์ ์ดํด๋ณด์. Extra ์นผ๋ผ์
Using where; Using temporary; Using filesort๋ผ๋ ์ฝ๋ฉํธ๊ฐ ํ์๋๋ค.- ์ด๋ ์กฐ์ธ์ ๊ฒฐ๊ณผ๋ฅผ ์์ ํ ์ด๋ธ์ ์ ์ฅํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ ๋ ฌ ์ฒ๋ฆฌํ์์ ์๋ฏธํ๋ค.
+----+-------+-------+---------+----------------------------------------------+
| id | table | type | key | Extra |
+----+-------+-------+---------+----------------------------------------------+
| 1 | e | range | PRIMARY | Using where; Using temporary; Using filesort |
| 1 | s | ref | PRIMARY | NULL |
+----+-------+-------+---------+----------------------------------------------+- ์น ์๋น์ค์ฉ ์ฟผ๋ฆฌ์์๋
ORDER BY์ ํจ๊ปLIMIT์ด ๊ฑฐ์ ํ์๋ก ์ฌ์ฉ๋๋ค.LIMIT์ ํ ์ด๋ธ์ด๋ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ์ ์ผ๋ถ๋ง ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์ MySQL ์๋ฒ๊ฐ ์ฒ๋ฆฌํด์ผ ํ ์์ ๋์ ์ค์ด๋ ์ญํ ์ ํ๋ค.
- ๊ทธ๋ฐ๋ฐ
ORDER BY๋GROUP BY๊ฐ์ ์์ ์WHERE์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋๋ฅผLIMIT๊ฑด์๋งํผ๋ง ๊ฐ์ ธ์์๋ ์ฒ๋ฆฌํ ์ ์๋ค.- ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์ ์ ๋ ฌ์ ์ํํ๊ฑฐ๋, ๊ทธ๋ฃจํ ์์
์ ์คํํด์ผ๋ง ๋น๋ก์
LIMIT์ผ๋ก ๊ฑด์๋ฅผ ์ ํํ ์ ์๋ค. - ์๋ฌด๋ฆฌ WHERE ์กฐ๊ฑด์ด ์ธ๋ฑ์ค๋ฅผ ์ ํ์ฉํ๋๋ก ํ๋ํด๋ ์๋ชป๋
ORDER BY๋GROUP BY๋๋ฌธ์ ์ฟผ๋ฆฌ๊ฐ ๋๋ ค์ง๋ ๊ฒฝ์ฐ๊ฐ ์์ฃผ ๋ฐ์ํ๋ค.
- ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์ ์ ๋ ฌ์ ์ํํ๊ฑฐ๋, ๊ทธ๋ฃจํ ์์
์ ์คํํด์ผ๋ง ๋น๋ก์
- ๋ ์ฝ๋๊ฐ ๊ฒ์๋ ๋๋ง๋ค ๋ฐ๋ก๋ฐ๋ก ํด๋ผ์ด์ธํธ๋ก ์ ์กํด์ฃผ๋ ๋ฐฉ์
- ์ผ์นํ๋ ๋ ์ฝ๋๋ฅผ ์ฐพ๋ ์ฆ์ ์ ๋ฌ๋ฐ๊ธฐ ๋๋ฌธ์ ๋์์ ๋ฐ์ดํฐ์ ๊ฐ๊ณต ์์
์ ์์ํ ์ ์๋ค.
- ์คํธ๋ฆฌ๋ฐ์ผ๋ก ์ฒ๋ฆฌ๋๋ ์ฟผ๋ฆฌ๋ ์ฟผ๋ฆฌ๊ฐ ์ผ๋ง๋ ๋ง์ ๋ ์ฝ๋๋ฅผ ์กฐํํ๋๋์ ์๊ด์์ด ๋น ๋ฅธ ์๋ต ์๊ฐ์ ๋ณด์ฅํด์ค๋ค.
- ๋ํ,
LIMIT์ฒ๋ผ ๊ฒฐ๊ณผ ๊ฑด์๋ฅผ ์ ํํ๋ ์กฐ๊ฑด๋ค์ ์ฟผ๋ฆฌ์ ์ ์ฒด ์คํ ์๊ฐ์ ์๋นํ ์ค์ฌ์ค ์ ์๋ค๋ฉด ์ฅ์ ์ด ์๋ค.
ORDER BY๋GROUP BY๊ฐ์ ์ฒ๋ฆฌ๋ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๊ฐ ์คํธ๋ฆฌ๋ฐ๋๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๊ฒ ํ๋ค.WHERE์กฐ๊ฑด์ ์ผ์นํ๋ ๋ชจ๋ ๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์จ ํ, ์ ๋ ฌํ๊ฑฐ๋ ๊ทธ๋ฃจํํด์ ์ฐจ๋ก๋๋ก ๋ณด๋ด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค.- MySQL ์๋ฒ์์๋ ๋ชจ๋ ๋ ์ฝ๋๋ฅผ ๊ฒ์ํ๊ณ ์ ๋ ฌ ์์ ์ ํ๋ ๋์ ํด๋ผ์ด์ธํธ๋ ์๋ฌด๊ฒ๋ ํ์ง ์๊ณ ๊ธฐ๋ค๋ ค์ผ ํ๊ธฐ ๋๋ฌธ์ ์๋ต ์๋๊ฐ ๋๋ ค์ง๋ค.
- ๋ฒํผ๋ง ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ๋๋ ์ฟผ๋ฆฌ๋ ๋จผ์ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์์ MySQL ์๋ฒ์์ ์ผ๊ด ๊ฐ๊ณตํด์ผ ํ๋ฏ๋ก ๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ ์คํ ๋ฆฌ์ง ์์ง์ผ๋ก๋ถํฐ ๊ฐ์ ธ์ฌ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ค.
- ๋ฐ๋ผ์
LIMIT์ฒ๋ผ ๊ฒฐ๊ณผ ๊ฑด์๋ฅผ ์ ํํ๋ ์กฐ๊ฑด์ด ์์ด๋ ์ฑ๋ฅ ํฅ์์ ๋ณ๋ก ๋์์ด ๋์ง ์๋๋ค. - ๋ ์ฝ๋ ๊ฑด์๋ ์ค์ผ ์ ์์ง๋ง MySQL ์๋ฒ๊ฐ ํด์ผํ๋ ์์ ๋์๋ ๊ทธ๋ค์ง ๋ณํ๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ฐ๋ผ์
ORDER BY์ 3๊ฐ์ง ์ฒ๋ฆฌ ๋ฐฉ๋ฒ ์ค ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ๋ ฌ ๋ฐฉ์๋ง ์คํธ๋ฆฌ๋ฐ ํํ์ ์ฒ๋ฆฌ์ด๋ค.- "์กฐ์ธ์์ ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌ"๊ณผ "์กฐ์ธ์์ ์กฐ์ธ ๊ฒฐ๊ณผ๋ฅผ ์์ ํ ์ด๋ธ๋ก ์ ์ฅ ํ ์ ๋ ฌ"์ ๋ชจ๋ ๋ฒํผ๋ง๋ ํ์ ์ ๋ ฌ๋๋ค.
- ์ฆ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ๋ฐฉ์์
LIMIT์ผ๋ก ์ ํ๋ ๊ฑด์๋งํผ๋ง ์ฝ์ผ๋ฉด ๋ฐ๋ก๋ฐ๋ก ํด๋ผ์ด์ธํธ๋ก ์ ์กํด์ค ์ ์๋ค๋ ๋ง์ด๋ค.
- ์์ ๊ฐ์
tb1์ ๋ ์ฝ๋๊ฐ 100๊ฑดtb2๋ ์ฝ๋๊ฐ 1,000๊ฑดtb1ํ ์ด๋ธ 1๊ฑด๋น,tb2ํ ์ด๋ธ 10๊ฑด์ด ์์์ ๊ฐ์ - ๋ ํ ์ด๋ธ ์กฐ์ธ ๊ฒฐ๊ณผ๋ ์ ์ฒด 1,000๊ฑด์ด๋ผ๊ณ ๊ฐ์ ํ ์์
- ๋จผ์
tb1์ด ๋๋ผ์ด๋น ํ ์ด๋ธ์ด๋ผ๊ณ ๊ฐ์ ํ์ ๋
| ์ ๋ ฌ ๋ฐฉ๋ฒ | ์ฝ์ด์ผ ํ ๊ฑด์ | ์กฐ์ธ ํ์ | ์ ๋ ฌํด์ผ ํ ๋์ ๊ฑด์ |
|---|---|---|---|
| ์ธ๋ฑ์ค ์ฌ์ฉ | ๋๋ผ์ด๋น ํ
์ด๋ธ: 1๊ฑด ๋๋ฆฌ๋ธ ํ ์ด๋ธ: 10๊ฑด |
1๋ฒ | 0๊ฑด |
| ์กฐ์ธ ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌ | ๋๋ผ์ด๋น ํ
์ด๋ธ: 100๊ฑด ๋๋ฆฌ๋ธ ํ ์ด๋ธ: 10๊ฑด |
1๋ฒ | 100๊ฑด(๋๋ผ์ด๋น ํ ์ด๋ธ ๊ฑด์๋งํผ ์ ๋ ฌ ํ์) |
| ์์ ํ ์ด๋ธ ์ฌ์ฉ ํ ์ ๋ ฌ | ๋๋ผ์ด๋น ํ
์ด๋ธ: 100๊ฑด ๋๋ฆฌ๋ธ ํ ์ด๋ธ: 1,000๊ฑด |
100๋ฒ(๋๋ผ์ด๋น ํ ์ด๋ธ ๊ฑด์๋งํผ ์กฐ์ธ ๋ฐ์) | 1,000๊ฑด(์กฐ์ธ๋ ๊ฒฐ๊ณผ ๋ ์ฝ๋ ๊ฑด์๋ฅผ ์ ๋ถ ์ ๋ ฌํด์ผ ํจ) |
tb2๊ฐ ๋๋ผ์ด๋น ํ ์ด๋ธ์ด๋ผ๊ณ ๊ฐ์ ํ์ ๋
| ์ ๋ ฌ ๋ฐฉ๋ฒ | ์ฝ์ด์ผ ํ ๊ฑด์ | ์กฐ์ธ ํ์ | ์ ๋ ฌํด์ผ ํ ๋์ ๊ฑด์ |
|---|---|---|---|
| ์ธ๋ฑ์ค ์ฌ์ฉ | ๋๋ผ์ด๋น ํ
์ด๋ธ: 10๊ฑด ๋๋ฆฌ๋ธ ํ ์ด๋ธ: 10๊ฑด |
10๋ฒ | 0๊ฑด |
| ์กฐ์ธ ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌ | ๋๋ผ์ด๋น ํ
์ด๋ธ: 1000๊ฑด ๋๋ฆฌ๋ธ ํ ์ด๋ธ: 10๊ฑด |
100๋ฒ | 1,000๊ฑด(๋๋ผ์ด๋น ํ ์ด๋ธ ๊ฑด์๋งํผ ์ ๋ ฌ ํ์) |
| ์์ ํ ์ด๋ธ ์ฌ์ฉ ํ ์ ๋ ฌ | ๋๋ผ์ด๋น ํ
์ด๋ธ: 1,000๊ฑด ๋๋ฆฌ๋ธ ํ ์ด๋ธ: 100๊ฑด |
1,000๋ฒ(๋๋ผ์ด๋น ํ ์ด๋ธ ๊ฑด์๋งํผ ์กฐ์ธ ๋ฐ์) | 1,000๊ฑด(์กฐ์ธ๋ ๊ฒฐ๊ณผ ๋ ์ฝ๋ ๊ฑด์๋ฅผ ์ ๋ถ ์ ๋ ฌํด์ผ ํจ) |
- ์ด๋ ํ ์ด๋ธ์ด ๋จผ์ ๋๋ผ์ด๋น๋์ด ์กฐ์ธ๋๋์ง๋ ์ค์ํ์ง๋ง ์ด๋ค ์ ๋ ฌ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ๋๋์ง๋ ๋ ํฐ ์ฑ๋ฅ ์ฐจ์ด๋ฅผ ๋ง๋ ๋ค.
- ๊ฐ๋ฅํ๋ค๋ฉด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ๋ ฌ๋ก ์ ๋ํ๊ณ , ๊ทธ๋ ์ง ๋ชปํ๋ค๋ฉด ์ต์ํ ๋๋ผ์ด๋น ํ ์ด๋ธ๋ง ์ ๋ ฌํด๋ ๋๋ ์์ค์ผ๋ก ์ ๋ํ๋ ๊ฒ์ด ์ข์ ํ๋ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ ์ ์๋ค.
๊ฐ์๊ธฐ ๊ถ๊ธํด์ ์ฐพ์๋ณธ ์ ๋ณด!
์์ฆ
date๋datetimeํ์ ์ ์ปฌ๋ผ์ผ๋ก ์ ๋ ฌํ ์ผ์ด ๋ง๋ค. ๊ทธ๋ฐ๋ฐ DATE_FORMAT์ ์ฌ์ฉํ๊ณ ์๋๋ฐ?!? MySQL์์๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ธ๋ฑ์ค๊ฐ ํ์ง๊น?์ ๋ต์ "์ธ๋ฑ์ค๋ฅผ ํ์ง ์๋๋ค"์ด๋ค. MySQL์์๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ธ๋ฑ์ค๋ฅผ ํ์ง ์๋๋ค๊ณ ํ๋ค. ์ ๊ธฐํ๋ ์ ์ BETWEEN๊ณผ ๊ฐ์ ํจ์ ๋ํ ์ธ๋ฑ์ค๋ฅผ ํ์ง ์๋๋ค๋ ์ ์ด๋ค! ๋๋ฌธ์ ์์ ํ๋ ๊ฒ์ด ์ข๋ค. ๋ ์ง๋ฅผ ๊ฒ์ํ ๋ ์๋ ์ฝ๋์ ๊ฐ์ด ๊ฒ์ํ์.
SELECT *
FROM order
where order_date >= '2023-11-21'
and order_date < '2023-11-22'SELECT *
FROM order
where order_date >= '2023-11-21 00:00:00'
and order_date < '2023-11-22 23:59:59'- MySQL ์๋ฒ๋ ์ฒ๋ฆฌํ๋ ์ฃผ์ ์์ ์ ๋ํด์๋ ํด๋น ์์ ์ ์คํ ํ์๋ฅผ ์ํ ๋ณ์๋ก ์ ์ฅํ๋ค.
- ์ง๊ธ๊น์ง ๋ช ๊ฑด์ ๋ ์ฝ๋๋ ์ ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋์ง, ์ํธ ๋ฒํผ ๊ฐ์ ๋ณํฉ ์์ ์ ๋ช ๋ฒ์ด๋ ๋ฐ์ํ๋์ง ๋ฑ์ ์๋ ๋ช ๋ น์ด๋ฅผ ํตํด ํ์ธํ ์ ์๋ค.
mysql> FLUSH STATUS;
mysql> SHOW STATUS LIKE 'Sort%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Sort_merge_passes | 0 |
| Sort_range | 0 |
| Sort_rows | 0 |
| Sort_scan | 0 |
+-------------------+-------+Sort_merge_passes๋ ๋ฉํฐ ๋จธ์ง ์ฒ๋ฆฌ ํ์๋ฅผ ์๋ฏธํ๋ค.Sort_range๋ ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ์ ํตํด ๊ฒ์๋ ๊ฒฐ๊ณผ์ ๋ํ ์ ๋ ฌ ์์ ํ์๋ค.Sort_rows๋ ์ง๊ธ๊น์ง ์ ๋ ฌํ ์ ์ฒด ๋ ์ฝ๋ ๊ฑด์๋ฅผ ์๋ฏธํ๋ค.Sort_scan์ ํ ํ ์ด๋ธ ์ค์บ์ ํตํด ๊ฒ์๋ ๊ฒฐ๊ณผ์ ๋ํ ์ ๋ ฌ ์์ ํ์๋ค.
GROUP BY๋ํORDER BY์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฟผ๋ฆฌ๊ฐ ์คํธ๋ฆฌ๋ฐ๋ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๊ฒ ํ๋ ๊ธฐ๋ฅ ์ค ํ๋๋ค.GROUP BY์์๋HAVING์ ์ ์ฌ์ฉํ ์ ์๋๋ฐ, ๊ฒฐ๊ณผ์ ๋ํด ํํฐ๋ง ์ญํ ์ ์ํํ๋ค.GROUP BY์์ ์ฌ์ฉ๋ ์กฐ๊ฑด์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํด์ ์ฒ๋ฆฌ๋ ์ ์์ผ๋ฏ๋กHAVING์ ์ ํ๋ํ๋ ค๊ณ ํ๋ ์ด๋ฆฌ์์์ ๋ฒํ์ง ๋ง์.GROUP BY๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ๊ทธ๋ ์ง ๋ชปํ ๊ฒฝ์ฐ๋ก ๋๋ ์ ์๋ค.- ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
- ์ธ๋ฑ์ค๋ฅผ ์ฐจ๋ก๋๋ก ์ฝ๋ ์ธ๋ฑ์ค ์ค์บ ๋ฐฉ๋ฒ
- ์ธ๋ฑ์ค๋ฅผ ๊ฑด๋๋ฐ๋ฉด์ ์ฝ๋ ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ ๋ฐฉ๋ฒ
- ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ
- ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ค.
- ์กฐ์ธ์ ๋๋ผ์ด๋น ํ
์ด๋ธ์ ์ํ ์ปฌ๋ผ๋ง ์ด์ฉํด ๊ทธ๋ฃจํํ ๋
GROUP BY์นผ๋ผ์ผ๋ก ์ด๋ฏธ ์ธ๋ฑ์ค๊ฐ ์๋ค๋ฉด ๊ทธ ์ธ๋ฑ์ค๋ฅผ ์ฐจ๋ก๋๋ก ์ฝ์ผ๋ฉด์ ๊ทธ๋ฃจํ ์์ ์ ์ํํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ก ์กฐ์ธ์ ์ฒ๋ฆฌํ๋ค. GROUP BY๊ฐ ์ธ๋ฑ์ค๋ก ์ฒ๋ฆฌ๋๋ค ํ๋๋ผ๋ ๊ทธ๋ฃน ํฉ์(Aggregation Function) ๋ฑ์ ๊ทธ๋ฃน๊ฐ์ ์ฒ๋ฆฌํด์ผ ํด์ ์์ ํ ์ด๋ธ์ด ํ์ํ ๋๋ ์๋ค.- ์ด๋ฌํ ๊ทธ๋ฃจํ ๋ฐฉ์์ ์ฌ์ฉํ๋ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์์๋ Extra ์นผ๋ผ์ ๋ณ๋๋ก
GROUP BY์ฝ๋ฉํธ "Using index for group-by"๋ ์์ ํ ์ด๋ธ ์ฌ์ฉ ๋๋ ์ ๋ ฌ ๊ด๋ จ ์ฝ๋ฉํธ "Using temporary, Using filesort"๊ฐ ํ์๋์ง ์๋๋ค.
- ์ธ๋ฑ์ค์ ๋ ์ฝ๋๋ฅผ ๊ฑด๋๋ฐ๋ฉด์ ํ์ํ ๋ถ๋ถ๋ง ์ฝ์ด์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
- ์ตํฐ๋ง์ด์ ๊ฐ ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ์ ์ฌ์ฉํ ๋๋ ์คํ ๊ณํ์ Extra ์นผ๋ผ์ "Using index for group-by" ์ฝ๋ฉํธ๊ฐ ํ์๋๋ค.
- ์์๋ฅผ ์ดํด๋ณด์. ์๋ ํ ์ด๋ธ์ (emp_no, from_date)์ ๊ทธ๋ฃน ํค๋ฅผ primary key๋ก ๊ฐ์ง๋ ํ ์ด๋ธ์ด๋ค.
mysql> desc salaries;
+-----------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------+------+-----+---------+-------+
| emp_no | int | NO | PRI | NULL | |
| salary | int | NO | MUL | NULL | |
| from_date | date | NO | PRI | NULL | |
| to_date | date | NO | | NULL | |
+-----------+------+------+-----+---------+-------+
4 rows in set (0.00 sec)mysql> EXPLAIN
-> SELECT emp_no
-> FROM salaries
-> WHERE from_date='1985-03-01'
-> GROUP BY emp_no;
+----+----------+-------+---------+--------+----------+---------------------------------------+
| id | table | type | key | rows | filtered | Extra |
+----+----------+-------+---------+--------+----------+---------------------------------------+
| 1 | salaries | range | PRIMARY | 299646 | 100.00 | Using where; Using index for group-by |
+----+----------+-------+---------+--------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)- ์ ์ฟผ๋ฆฌ๋ ์๋์ ์์๋๋ก ์คํ๋๋ค.
(emp_no, from_date)์ธ๋ฑ์ค๋ฅผ ์ฐจ๋ก๋๋ก ์ค์บํ๋ฉดemp_no์ ์ฒซ ๋ฒ์งธ ์ ์ผํ ๊ฐ(๊ทธ๋ฃน ํค) '10001'์ ์ฐพ์๋ธ๋ค.(emp_no, from_date)์ธ๋ฑ์ค์์emp_no๊ฐ '10001'์ธ ๊ฒ ์ค์์ from_date ๊ฐ์ด '1985-03-01'์ธ ๋ ์ฝ๋๋ง ๊ฐ์ ธ์จ๋ค.- '10001' ๊ฐ๊ณผ WHERE ์ ์ ์ฌ์ฉ๋
from_date='1985-03-01'์กฐ๊ฑด์ ํฉ์ณ์emp_no=10001 AND from_date='1985-03-01'์กฐ๊ฑด์ผ๋ก (emp_no, from_date) ์ธ๋ฑ์ค๋ฅผ ๊ฒ์ํ๋ ๊ฒ๊ณผ ๊ฑฐ์ ํก์ฌํ๋ค.
- '10001' ๊ฐ๊ณผ WHERE ์ ์ ์ฌ์ฉ๋
(emp_no, from_date)์ธ๋ฑ์ค์์emp_no์ ๊ทธ ๋ค์ ์ ๋ํฌํ ๊ฐ์ ๊ฐ์ ธ์จ๋ค. (๊ทธ๋ฃนํค)- ๊ฒฐ๊ณผ๊ฐ ๋ ์์ผ๋ฉด ์ฒ๋ฆฌ๋ฅผ ์ข ๋ฃํ๊ณ ๊ฒฐ๊ณผ๊ฐ ์๋ค๋ฉด 2๋ฒ ๊ณผ์ ์ผ๋ก ๋์๊ฐ ๋ฐ๋ณต ์ํํ๋ค.
- MySQL์ ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ ๋ฐฉ์์ ๋จ์ผ ํ
์ด๋ธ์ ๋ํด ์ํ๋๋
GROUP BY์ฒ๋ฆฌ์๋ง ์ฌ์ฉํ ์ ์๋ค. - ๋ํ
Prefix Index, ์นผ๋ผ์ ์์ชฝ ์ผ๋ถ๋ง์ผ๋ก ์์ฑ๋ ์ธ๋ฑ์ค๋ ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ์ ์ฌ์ฉํ ์ ์๋ค. - ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ์ ์ ๋ํฌํ ๊ฐ์ ์๊ฐ ๋ง์์๋ก ์ฑ๋ฅ์ด ํฅ์๋๋ ๋ฐ๋ฉด ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ์์๋ ์ธ๋ฑ์ค์ ์ ๋ํฌํ ๊ฐ์ ์๊ฐ ์ ์์๋ก ์ฑ๋ฅ์ด ํฅ์๋๋ค.
- ์ฆ, ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ์ ๋ถํฌ๋๊ฐ ์ข์ง ์์ ์ธ๋ฑ์ค์ผ์๋ก ๋ ๋น ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ด๋ธ๋ค.
- ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ์ด ์ฌ์ฉ๋ ์ ์์์ง ์์์ง ํ๋จํ๋ ๊ฒ์ WHERE ์ ์ ์กฐ๊ฑด์ด๋ ORDER BY ์ ์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์์ง ์์์ง ํ๋จํ๋ ๊ฒ๋ณด๋ค๋ ๋ ์ด๋ ต๋ค.
- ๊ธฐ์ค ์นผ๋ฝ์ด ๋๋ผ์ด๋น ํ ์ด๋ธ์ ์๋ ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ ์๋ ๊ด๊ณ ์์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ค๋ฉด ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ค.
- ์คํ ๊ณํ์ ์ดํด๋ณด๋ฉด Extra ์นผ๋ผ์ "Using temporary"๋ผ๋ ๋ฉ์์ง๊ฐ ํ์๋๋ค.
mysql> EXPLAIN
SELECT e.last_name, AVG(s.salary)
FROM employees e, salaries s
WHERE s.emp_no = e.emp_no
GROUP BY e.last_name;
+----+-------+------+---------+--------+-----------------+
| id | table | type | key | rows | Extra |
+----+-------+------+---------+--------+-----------------+
| 1 | e | ALL | NULL | 300252 | Using temporary |
| 1 | s | ref | PRIMARY | 9 | NULL |
+----+-------+------+---------+--------+-----------------+
2 rows in set, 1 warning (0.00 sec)- MySQL 8.0 ์ด์ ๋ฒ์ ๊น์ง๋
GROUP BY๊ฐ ์ฌ์ฉ๋ ์ฟผ๋ฆฌ๋ ๊ทธ๋ฃจํ๋๋ ์นผ๋ผ์ ๊ธฐ์ค์ผ๋ก ๋ฌต์์ ์ธ ์ ๋ ฌ๊น์ง ์ํํ๋ค.GROUP BY๋ง ํด๋ Extra์ "Using temporary"์ "Using filesort"๊ฐ ๊ฐ์ด ์ฐํ๋ค๋ ์๊ธฐ๋ค.
- ํ์ง๋ง MySQL 8.0์์๋ GROUP BY๊ฐ ํ์ํ ๊ฒฝ์ฐ ๋ด๋ถ์ ์ผ๋ก
GROUP BY์ ์ ์นผ๋ผ๋ค๋ก ๊ตฌ์ฑ๋ ์ ๋ํฌ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง ์์ ํ ์ด๋ธ์ ๋ง๋ค์ด์ ์ค๋ณต ์ ๊ฑฐ์ ์งํฉ ํจ์ ์ฐ์ฐ์ ์ํํ๋ค.- ๊ทธ๋ฆฌ๊ณ ์กฐ์ธ์ ๊ฒฐ๊ณผ๋ฅผ ํ ๊ฑด์ฉ ๊ฐ์ ธ์ ์์ ํ
์ด๋ธ์์ ์ค๋ณต ์ฒดํฌ๋ฅผ ํ๋ฉด์
INSERT๋๋UPDATE๋ฅผ ์คํํ๋ค.
- ๊ทธ๋ฆฌ๊ณ ์กฐ์ธ์ ๊ฒฐ๊ณผ๋ฅผ ํ ๊ฑด์ฉ ๊ฐ์ ธ์ ์์ ํ
์ด๋ธ์์ ์ค๋ณต ์ฒดํฌ๋ฅผ ํ๋ฉด์
CREATE TEMPORARY TABLE ... (
last_name VARCHAR(16),
salary INT,
UNIQUE INDEX ux_lastname(last_name)
)GROUP BY์ORDER BY๊ฐ ๊ฐ์ด ์คํ๋๋ฉด ๋ช ์์ ์ผ๋ก ์ ๋ ฌ ์์ ์ ์ํํ๋๋ฐ Extra ์นผ๋ผ์ "Using temporary์ Using filesort"๊ฐ ๊ฐ์ด ํ์๋๋ค.
mysql> EXPLAIN
SELECT e.last_name, AVG(s.salary)
FROM employees e, salaries s
WHERE s.emp_no = e.emp_no
GROUP BY e.last_name
ORDER BY e.last_name;
+----+-------+------+---------+--------+---------------------------------+
| id | table | type | key | rows | Extra |
+----+-------+------+---------+--------+---------------------------------+
| 1 | e | ALL | NULL | 300252 | Using temporary; Using filesort |
| 1 | s | ref | PRIMARY | 9 | NULL |
+----+-------+------+---------+--------+---------------------------------+
2 rows in set, 1 warning (0.00 sec)- ํน์ ์นผ๋ผ์ ์ ๋ํฌํ ๊ฐ๋ง ์กฐํํ๋ ค๋ฉด
SELECT์ฟผ๋ฆฌ์DISTINCT๋ฅผ ์ฌ์ฉํ๋ค. MIN,MAX,COUNT์ ๊ฐ์ ์งํฉ์ ํจ๊ป ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ์ ์งํฉ ํจ์๊ฐ ์๋ ๊ฒฝ์ฐ 2๊ฐ์ง๋ก ๊ตฌ๋ถํด์ ๋ณผ ์ ์๋ค.- ๊ฐ ๊ฒฝ์ฐ๋ง๋ค
DISTINCTํค์๋๊ฐ ๋ฏธ์น๋ ๋ฒ์๊ฐ ๋ฌ๋ผ์ง๋ค.
- ๊ฐ ๊ฒฝ์ฐ๋ง๋ค
- ๋ํ
DISTINCE์ฒ๋ฆฌ๊ฐ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ ๋ ํญ์ ์์ ํ ์ด๋ธ์ด ํ์ํ๋ค. ํ์ง๋ง ์คํ ๊ณํ์ Extra ์นผ๋ผ์๋ "Using temporary" ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋์ง ์๋๋ค.
- ๋จ์ํ
SELECT๋๋ ๋ ์ฝ๋ ์ค์์ ์ ๋ํฌํ ๋ ์ฝ๋๋ง ๊ฐ์ ธ์ค๊ณ ์ ํ๋ฉดSELECT DISTINCTํํ์ ์ฟผ๋ฆฌ ๋ฌธ์ฅ์ ์ฌ์ฉํ๋ค.- ์ด ๊ฒฝ์ฐ์๋
GROUP BY์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
- ์ด ๊ฒฝ์ฐ์๋
- ํนํ MySQL 8.0 ๋ฒ์ ๋ถํฐ๋
GROUP BY๋ฅผ ์ํํ๋ ์ฟผ๋ฆฌ์ORDER BY์ ์ด ์์ผ๋ฉด ์ ๋ ฌ์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ค์์ ๋ ์ฟผ๋ฆฌ๋ ๋ด๋ถ์ ์ผ๋ก ๊ฐ์ ์์ ์ ์ํํ๋ค.
mysql> SELECT DISTINCT emp_no FROM salaries;
mysql> SELECT emp_no FROM salaries GROUP BY emp_no;- ํ๋ ์ฃผ์ํ ์ ์ด ์๋๋ฐ, DISTINCT๋ SELECTํ๋ ๋ ์ฝ๋(ํํ)์ ์ ๋ํฌํ๊ฒ
SELECTํ๋ ๊ฒ์ด์ง, ํน์ ์นผ๋ผ๋ง ์ ๋ํฌํ๊ฒ ์กฐํํ๋ ๊ฒ์ด ์๋๋ค. - ๊ทธ๋ฐ๋ฐ ์๋์ ๊ฐ์ด DISTINCT๋ฅผ ํจ์์ฒ๋ผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ์๋ค.
SELECT DISTINCT(first_name), last_name FROM employees;- ๋ฌธ์ ์์ด ์คํ๋๋ ๊ฒ ๊ฐ์ ๋ณด์ด์ง๋ง, MySQL ์๋ฒ๋
DISTINCT๋ค์ ๊ดํธ๋ฅผ ๊ทธ๋ฅ ์๋ฏธ ์์ด ์ฌ์ฉ๋ ๊ดํธ๋ก ํด์ํ๊ณ ์ ๊ฑฐํด๋ฒ๋ฆฐ๋ค.DISTINCT๋ ํจ์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๊ทธ ๋ค์ ๊ดํธ๋ ์๋ฏธ๊ฐ ์๋ ๊ฒ์ด๋ค. - ๋ฐ๋ผ์
SELECT์ ์ ์ฌ์ฉ๋DISTINCTํค์๋๋ ์กฐํ๋๋ ๋ชจ๋ ์นผ๋ผ์ ์ํฅ์ ๋ฏธ์น๋ค. - ๋จ, ์ด์ด์ ์ค๋ช
ํ ์งํฉ ํจ์์ ํจ๊ป ์ฌ์ฉ๋
DISTINCT์ ๊ฒฝ์ฐ ์กฐ๊ธ ๋ค๋ฅด๋ค.
- ์งํฉ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก
SELECT DISTINCT์๋ ๋ค๋ฅด๊ฒ ํด์๋๋ค. - ์งํฉ ํจ์ ๋ด์์ ์ฌ์ฉ๋
DISTINCT๋ ๊ทธ ์งํฉ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋ ์นผ๋ผ๊ฐ์ด ์ ๋ํฌํ ๊ฒ๋ค์ ๊ฐ์ ธ์จ๋ค.
mysql> EXPLAIN
SELECT COUNT(DISTINCT s.salary)
FROM employees e, salaries s
WHERE e.emp_no = s.emp_no
AND e.emp_no BETWEEN 100001 AND 100100;
+----+-------+-------+---------+------+--------------------------+
| id | table | type | key | rows | Extra |
+----+-------+-------+---------+------+--------------------------+
| 1 | e | range | PRIMARY | 100 | Using where; Using index |
| 1 | s | ref | PRIMARY | 9 | NULL |
+----+-------+-------+---------+------+--------------------------+
2 rows in set, 1 warning (0.00 sec)- ์ ์ฟผ๋ฆฌ๋ ๋ด๋ถ์ ์ผ๋ก
COUNT(DISTINCT s.salary)๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ค. - ํ์ง๋ง ์คํ ๊ณํ์๋ ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ค๋ ๋ฉ์์ง์ธ "Using temporary"๊ฐ ๋ณด์ด์ง ์๋๋ค.
- ์ด๋ ์์ ํ ์ด๋ธ์ salary ์นผ๋ผ์๋ ์ ๋ํฌ ์ธ๋ฑ์ค๊ฐ ์์ฑ๋๊ธฐ ๋๋ฌธ์ ๋ ์ฝ๋ ๊ฑด์๊ฐ ๋ง์์ง๋ค๋ฉด ์๋นํ ๋๋ ค์ง ์ ์๋ ํํ์ ์ฟผ๋ฆฌ๊ฐ ๋๋ค.
- MySQL ์์ง์ด ์คํ ๋ฆฌ์ง ์์ง์ผ๋ก๋ถํฐ ๋ฐ์์จ ๋ ์ฝ๋๋ฅผ ์ ๋ ฌํ๊ฑฐ๋ ๊ทธ๋ฃจํํ ๋๋ ๋ด๋ถ ์์ ํ ์ด๋ธ(Internal temporary table)์ ์ฌ์ฉํ๋ค.
- ๋ด๋ถ ์์ ํ
์ด๋ธ์
CREATE TEMPORARY TABLE๋ช ๋ น์ผ๋ก ๋ง๋ ์์ ํ ์ด๋ธ๊ณผ๋๋ ๋ค๋ฅด๋ค. - ์ผ๋ฐ์ ์ธ ์์ ํ
์ด๋ธ์ ์ฒ์์ ๋ฉ๋ชจ๋ฆฌ์ ์์ฑ๋๋ค๊ฐ ํ
์ด๋ธ์ ํฌ๊ธฐ๊ฐ ์ปค์ง๋ฉด ๋์คํฌ๋ก ์ฎ๊ฒจ์ง๋ค.
- ํน์ ์์ธ ์ผ์ด์ค์๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฑฐ์น์ง ์๊ณ ๋ฐ๋ก ๋์คํฌ์ ๋ง๋ค์ด์ง๊ธฐ๋ ํ๋ค.
- ๋ด๋ถ ์์ ํ
์ด๋ธ์ ๋ด๋ถ์ ์ธ ๊ฐ๊ณต์ ์ํด MySQL ์์ง์ด ์ง์ ์์ฑํ๋ฉฐ ๋ค๋ฅธ ์ธ์
์ด๋ ๋ค๋ฅธ ์ฟผ๋ฆฌ์์ ๋ณผ ์ ์์ผ๋ฉฐ ์ฌ์ฉํ๋ ๊ฒ๋ ๋ถ๊ฐ๋ฅํ๋ค.
- ๋ํ ์ฟผ๋ฆฌ์ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋๋ฉด ์๋์ผ๋ก ์ญ์ ๋๋ค๋ ์ ์์ ์ฌ์ฉ์๊ฐ ์์ฑํ๋ ์์ ํ ์ด๋ธ๊ณผ๋ ๋ค๋ฅด๋ค.
- MySQL 8.0 ์ด์ ์๋ ์์ ํ
์ด๋ธ์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋๋ MEMORY ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ๊ณ , ๋์คํฌ์ ์ ์ฅ๋ ๋๋ MyISAM ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ๋ค.
- MEMORY ์คํ ๋ฆฌ์ง ์์ง์ ๊ฐ๋ณ ๊ธธ์ด ํ์
(
VARBINARY,VARCHAR)์ ์ง์ํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์์ ํ ์ด๋ธ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ง๋ค์ด์ง๋ฉด ๊ฐ๋ณ ํ์ ์ ๊ฒจ์ฐ ์ต๋ ๊ธธ์ด ๋งํผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ๊ธฐ ๋๋ฌธ์ ๋ญ๋น๊ฐ ์ฌํ๋ค. - ๋ํ MyISAM์์ ๋์คํฌ์ ์์ ํ ์ด๋ธ์ ๋ง๋ค์์ ๋ ํธ๋์ญ์ ์ ์ง์ํ์ง ๋ชปํ๋ค๋ ๋ฌธ์ ์ ์ ๊ฐ์ง๊ณ ์์๋ค.
- MEMORY ์คํ ๋ฆฌ์ง ์์ง์ ๊ฐ๋ณ ๊ธธ์ด ํ์
(
- 8.0 ๋ฒ์ ๋ถํฐ๋ ๋ฉ๋ชจ๋ฆฌ๋
TempTable์ด๋ผ๋ ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ๊ณ , ๋์คํฌ์ ์ ์ฅ๋๋ ์์ ํ ์ด๋ธ์ InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํ๋ค.TempTable์ ๊ฐ๋ณ ๊ธธ์ด ํ์ ์ ์ง์ํ๋ค.
- 8.0 ๋ฒ์ ์์๋
internal_tmp_storage_engine์์คํ ๋ณ์๋ฅผ ์ด์ฉํด MEMORY์ TempTable ์ค์์ ์ ํํ ์ ์๋ค. (default = TempTable) TempTable์ด ์ต๋ํ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํฌ๊ธฐ๋temptable_max_ram์์คํ ๋ณ์๋ก ์ ์ดํ ์ ์๋ค.- ๊ธฐ๋ณธ๊ฐ์ 1GB์ผ๋ก ์ค์ ๋์ด ์๋ค. ์์ ํ
์ด๋ธ์ ํฌ๊ธฐ๊ฐ 1GB๋ณด๋ค ์ปค์ง๋ฉด MySQL ์๋ฒ๋ ์์ ํ
์ด๋ธ์ ๋์คํฌ์ ๊ธฐ๋กํ๋ค. (์๋ 2๊ฐ์ง ๋ฐฉ์)
- MMAP ํ์ผ๋ก ๋์คํฌ์ ๊ธฐ๋ก
- InnoDB ํ ์ด๋ธ๋ก ๊ธฐ๋ก
- MySQL ์๋ฒ๊ฐ MMAP ํ์ผ๋ก ๊ธฐ๋กํ ์ง InnoDB ํ
์ด๋ธ๋ก ์ ํํ ์ง๋
temptable_use_mmap์์คํ ๋ณ์๋ก ์ค์ ํ ์ ์๋๋ฐ, ๊ธฐ๋ณธ๊ฐ์ ON์ผ๋ก ์ค์ ๋์ด ์๋ค.- ์ฆ, ๋ฉ๋ชจ๋ฆฌ์
TempTable์ ํฌ๊ธฐ๊ฐ 1GB๊ฐ ๋์ผ๋ฉด MySQL ์๋ฒ๋ ๋ฉ๋ชจ๋ฆฌ์TempTable์ MMAP ํ์ผ๋ก ์ ํํ๊ฒ ๋๋ค. - ๋ฉ๋ชจ๋ฆฌ์
TempTable์ MMAP ํ์ผ๋ก ์ ํํ๋ ๊ฒ์ InnoDB ํ ์ด๋ธ๋ก ์ ํํ๋ ๊ฒ๋ณด๋ค ์ค๋ฒํค๋๊ฐ ์ ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ๊ฐ์ด ON์ธ ๊ฒ์ด๋ค. - ์ด ๋ ๋์คํฌ์ ์์ฑ๋๋ ์์ ํ
์ด๋ธ์
tmpdir์์คํ ๋ณ์์ ์ ์๋ ๋ํ ํฐ๋ฆฌ์ ์ ์ฅ๋๋ค.
- ์ฆ, ๋ฉ๋ชจ๋ฆฌ์
- ์ฒ์๋ถํฐ ๋์คํฌ ํ ์ด๋ธ๋ก ์์ฑ๋๋ ๊ฒฝ์ฐ๋ ์๋ค. ์ด ๊ฒฝ์ฐ internal_tmp_disk_storage_engine ์์คํ ๋ณ์์ ์ค์ ๋ ์คํ ๋ฆฌ์ง ์์ง์ด ์ฌ์ฉ๋๋ค. (default = InnoDB)
- MySQL ์๋ฒ๋ ๋์คํฌ์ ์์ ํ ์ด๋ธ์ ์์ฑํ ๋, ํ์ผ ์คํ ํ ์ฆ์ ํ์ผ ์ญ์ ๋ฅผ ์คํํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ํด๋น ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ค.
- ์ด๋ฅผ ํตํด ์๋ฒ๊ฐ ์ข ๋ฃ๋๊ฑฐ๋ ํด๋น ์ฟผ๋ฆฌ๊ฐ ์ข ๋ฃ๋๋ฉด ์์ ํ ์ด๋ธ์ ์ฆ์ ์ฌ๋ผ์ง๊ฒ ๋ณด์ฅํ๋ ๊ฒ์ด๋ค.
- ๋ํ ์๋ฒ ๋ด๋ถ์ ๋ค๋ฅธ ์ค๋ ๋ ๋๋ ์๋ฒ ์ธ๋ถ์์ ์ฌ์ฉ์๊ฐ ํด๋น ์์ ํ ์ด๋ธ์ ์ํ ํ์ผ์ ๋ณ๊ฒฝ ๋ฐ ์ญ์ ํ๊ฑฐ๋ ๋ณผ ์ ์๊ฒ ํ๋ ๊ฒ์ด๋ค.
- ์ด ๊ฐ์ ์ด์ ๋ก ๋์ผ์ ์ ์ฅ๋ ์์ ํ ์ด๋ธ์ด ์ ์ฅ๋๋ ํ์ผ์ ์ด์์ฒด์ ์
dir๋๋ls -al๊ฐ์ ๋ช ๋ น์ผ๋ก๋ ํ์ธํ ์ ์๋ค.
- ๋ฆฌ๋ ์ค๋ ์ ๋์ค ๋ช ๋ น์ด์ธ
lsof -p 'pidof mysqld'๋ช ๋ น์ผ๋ก ํ์ธํด๋ "deleted"๋ก ํ์๋ ๊ฒ์ด๋ค.
- ๋ํ์ ์ธ ์ผ์ด์ค๋ค
ORDER BY์GROUP BY์ ๋ช ์๋ ์นผ๋ผ์ด ๋ค๋ฅธ ์ฟผ๋ฆฌORDER BY๋GROUP BY์ ๋ช ์๋ ์นผ๋ผ์ด ์กฐ์ธ์ ์์์ ์ฒซ ๋ฒ์งธ ํ ์ด๋ธ์ด ์๋ ์ฟผ๋ฆฌDISTINCT์ORDER BY๊ฐ ๋์์ ์ฟผ๋ฆฌ์ ์กด์ฌํ๋ ๊ฒฝ์ฐ ๋๋DISTINCT๊ฐ ์ธ๋ฑ์ค๋ก ์ฒ๋ฆฌ๋์ง ๋ชปํ๋ ์ฟผ๋ฆฌUNION์ด๋UNION DISTINCT๊ฐ ์ฌ์ฉ๋ ์ฟผ๋ฆฌ(select_type์นผ๋ผ์ดUNION RESULT์ธ ๊ฒฝ์ฐ)- ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์์
select_type์ดDERIVED์ธ ์ฟผ๋ฆฌ
- Extra ์นผ๋ผ์ "Using temporary" ๋ฉ์์ง๊ฐ ํ์๋๋์ง ํ์ธํ๋ฉด ์์ํ ์ด๋ธ์ด ์ฌ์ฉ๋๋์ง ํ์ธํ ์ ์๋ค. (์ฌ์ฉํ๋๋ผ๋ ํ์๋์ง ์๋ ๊ฒฝ์ฐ๊ฐ ์์ผ๋ ์ฃผ์ํ์. - 3๋ฒ์งธ ์ผ์ด์ค)
- ์์ 3๋ฒ์งธ ํจํด "Using temporary"๊ฐ ํ์๋์ง ์์ง๋ง ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ ์ผ์ด์ค๋ค.
- ์๋์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์์ ํ
์ด๋ธ์ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
UNION์ด๋UNION ALL์์SELECT๋๋ ์นผ๋ผ ์ค์์ ๊ธธ์ด๊ฐ 512๋ฐ์ดํธ ์ด์์ ํฌ๊ธฐ์ ์นผ๋ผ์ด ์๋ ๊ฒฝ์ฐGROUP BY๋DISTINCT์นผ๋ผ์์ 512๋ฐ์ดํธ ์ด์์ธ ํฌ๊ธฐ์ ์นผ๋ผ์ด ์๋ ๊ฒฝ์ฐ- (MEMORY ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ ๊ฒฝ์ฐ) ๋ฉ๋ชจ๋ฆฌ ์์ ํ
์ด๋ธ์ ํฌ๊ธฐ๊ฐ
tmp_table_size๋๋max_heap_table_size์์คํ ๋ณ์๋ณด๋ค ํฐ ๊ฒฝ์ฐ - (TempTable ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ ๊ฒฝ์ฐ) ๋ฉ๋ชจ๋ฆฌ ์์ ํ
์ด๋ธ์ ํฌ๊ธฐ๊ฐ
temptable_max_ram์์คํ ๋ณ์ ๊ฐ๋ณด๋ค ํฐ ๊ฒฝ์ฐ
- ์์ ํ ์ด๋ธ์ด ๋์คํฌ์ ์์ฑ๋๋์ง ๋ฉ๋ชจ๋ฆฌ์ ์์ฑ๋๋์ง ํ์ธํ๋ ค๋ฉด MySQL ์๋ฒ์ ์ํ ๋ณ์๋ฅผ ํ์ธํด ๋ณด๋ฉด ๋๋ค.
mysql> FLUSH STATUS;
mysql> SELECT first_name, last_name
FROM employees
GROUP BY first_name, last_name;
mysql> SHOW SESSION STATUS LIKE 'Created_tmp%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 1 |
| Created_tmp_files | 0 |
| Created_tmp_tables | 1 |
+-------------------------+-------+Created_tmp_disk_tables: ๋์คํฌ์ ๋ด๋ถ ์์ ํ ์ด๋ธ์ด ๋ง๋ค์ด์ง ๊ฐ์๋ง ๋์ ํด์ ๊ฐ์ง๊ณ ์๋ ์ํ ๊ฐ์ด๋ค.Created_tmp_tables: ์ฟผ๋ฆฌ์ ์ฒ๋ฆฌ๋ฅผ ์ํด ๋ง๋ค์ด์ง ๋ด๋ถ ์์ ํ ์ด๋ธ์ ๊ฐ์๋ฅผ ๋์ ํ๋ ์ํ ๊ฐ์ด๋ค. ์ด ๊ฐ์ ๋ด๋ถ ์์ ํ ์ด๋ธ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ง๋ค์ด์ก๋์ง ๋์คํฌ์ ๋ง๋ค์ด์ก๋์ง๋ฅผ ๊ตฌ๋ถํ์ง ์๊ณ ๋ชจ๋ ๋์ ํ๋ค.
- MySQL ์๋ฒ์ ์ตํฐ๋ง์ด์ ๊ฐ ์คํ ๊ณํ์ ์๋ฆฝํ ๋ ํต๊ณ ์ ๋ณด์ ์ตํฐ๋ง์ด์ ์ต์ ์ ๊ฒฐํฉํด์ ์ต์ ์ ์คํ ๊ณํ์ ์๋ฆฝํ๊ฒ ๋๋ค.
- ์ตํฐ๋ง์ด์ ์ต์
์ ์กฐ์ธ ๊ด๋ จ๋ ์ตํฐ๋ง์ด์ ์ต์
๊ณผ ์ตํฐ๋ง์ด์ ์ค์์น๋ก ๊ตฌ๋ถํ ์ ์๋ค.
- ์กฐ์ธ ๊ด๋ จ๋ ์ตํฐ๋ง์ด์ ์ต์ ์ MySQL ์๋ฒ ์ด๊ธฐ ๋ฒ์ ๋ถํฐ ์ ๊ณต๋๋ ์ต์ ์ด์ง๋ง, ๋ง์ ์ฌ๋์ด ๊ทธ๋ค์ง ์ ๊ฒฝ ์ฐ์ง ์๋ ํธ์ด๋ค. ํ์ง๋ง ์กฐ์ธ์ด ๋ง์ด ์ฌ์ฉ๋๋ ์๋น์ค์์๋ ์์์ผ ํ๋ ๋ถ๋ถ์ด๊ธฐ๋ ํ๋ค.
- ์ตํฐ๋ง์ด์ ์ค์์น๋ MySQL 5.5๋ถํฐ ์ง์๋๊ธฐ ์์ํ๊ณ , ์ด๋ค์ MySQL ์๋ฒ์ ๊ณ ๊ธ ์ต์ ํ ๊ธฐ๋ฅ๋ค์ ํ์ฑํํ ์ง๋ฅผ ์ ์ดํ๋ ์ฉ๋๋ก ์ฌ์ฉ๋๋ค.
optimizer_switch์์คํ ๋ณ์๋ฅผ ์ด์ฉํด์ ์ ์ดํ๋ฉฐ, ์ฌ๋ฌ ๊ฐ์ ์ต์ ์ ์ธํธ๋ก ๋ฌถ์ด์ ์ค์ ํ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.- ๊ฐ ์ค์์น ์ต์
์
default,on,off์ค์์ ํ๋๋ฅผ ๊ณ ๋ฅผ ์ ์๋ค.
| ์ตํฐ๋ง์ด์ ์ค์์น ์ด๋ฆ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
batched_key_access |
off |
BKA ์กฐ์ธ ์๊ณ ๋ฆฌ์ฆ ๊ฒฐ์ |
block_nested_loop |
on |
Block Nested Loop ์กฐ์ธ ์๊ณ ๋ฆฌ์ฆ ์ค์ |
engine_condition_pushdown |
on |
Engine Condition Pushdown ๊ธฐ๋ฅ ์ค์ |
index_condition_pushdown |
on |
Index Condition Pushdown ๊ธฐ๋ฅ ์ค์ |
use_index_extensions |
on |
Index Extension ์ต์ ํ ์ค์ |
index_merge |
on |
Index Merge ์ต์ ํ ์ค์ |
index_merge_intersection |
on |
Index Merge Intersection ์ต์ ํ ์ค์ |
index_merge_sort_union |
on |
Index Merge Union ์ต์ ํ ์ค์ |
mrr |
on |
MRR ์ต์ ํ ์ค์ |
mrr_cost_based |
on |
๋น์ฉ ๊ธฐ๋ฐ์ MRR ์ต์ ํ ์ค์ |
semijoin |
on |
์ธ๋ฏธ ์กฐ์ธ ์ต์ ํ ์ค์ |
firstmatch |
on |
FirstMatch ์ธ๋ฏธ ์กฐ์ธ ์ต์ ํ |
loosescan |
on |
LooseScan ์ธ๋ฏธ ์กฐ์ธ ์ต์ ํ ์ค์ |
materialization |
on |
Materialization ์ต์ ํ ์ค์ (Materialization ์ธ๋ฏธ ์กฐ์ธ ์ต์ ํ ํฌํจ) |
subquery_materialization_cost_based |
on |
๋น์ฉ ๊ธฐ๋ฐ์ Materialization ์ต์ ํ ์ค์ |
- ์ตํฐ๋ง์ด์ ์ค์์น ์ต์ ์ ๊ธ๋ก๋ฒ๊ณผ ์ธ์ ๋ณ ๋ชจ๋ ์ค์ ํ ์ ์๋ ์์คํ ๋ณ์์ด๋ฏ๋ก MySQL ์๋ฒ ์ ์ฒด์ ์ผ๋ก ๋๋ ํ์ฌ ์ปค๋ฅ์ ์ ๋ํด์๋ง ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ ์ ์๋ค.
- Global ์ค์
mysql> SET GLOBAL optimizer_switch='index_merge=on,index_merge_union=on';- Session๋ณ ์ค์
mysql> SET SESSION optimizer_switch='index_merge=on,index_merge_union=on';- ์๋์ ๊ฐ์ด
SET_VAR์ตํฐ๋ง์ด์ ํํธ๋ฅผ ์ด์ฉํ๋ฉด ํ์ฌ ์ฟผ๋ฆฌ์๋ง ์ค์ ํ ์๋ ์๋ค.
mysql> SELECT /*+ SET_VAR(optimizer_switch='condition_fanout_filter=off') */
*
FROM employees
LIMIT 1;
+--------+------------+------------+-----------+--------+------------+
| emp_no | birth_date | first_name | last_name | gender | hire_date |
+--------+------------+------------+-----------+--------+------------+
| 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 |
+--------+------------+------------+-----------+--------+------------+
1 row in set (0.00 sec)- MRR(Multi-Range Read)๋ DS-MRR(Disk Sweep Multi-Range Read)์ด๋ผ๊ณ ๋ ๋ถ๋ฅธ๋ค.
- MySQL ์๋ฒ์์ ์ง๊ธ๊น์ง ์ง์ํ๋ ์กฐ์ธ ๋ฐฉ์์ ๋๋ผ์ด๋น ํ
์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ํ ๊ฑด ์ฝ์ด์ ๋๋ฆฌ๋ธ ํ
์ด๋ธ์ ์ผ์นํ๋ ๋ ์ฝ๋๋ฅผ ์ฐพ์์ ์กฐ์ธ์ ์ํํ๋ ๊ฒ์ด์๋ค.
- ์ด๋ฅผ
๋ค์คํฐ๋ ๋ฃจํ ์กฐ์ธ Nested Loop Join์ด๋ผ๊ณ ํ๋ค. - MySQL ์๋ฒ ๋ด๋ถ ๊ตฌ์กฐ์ ์กฐ์ธ ์ฒ๋ฆฌ๋ MySQL ์์ง์ด ์ฒ๋ฆฌํ์ง๋ง, ์ค์ ๋ ์ฝ๋๋ฅผ ๊ฒ์ํ๊ณ ์ฝ๋ ๋ถ๋ถ์ ์คํ ๋ฆฌ์ง ์์ง์ด ๋ด๋นํ๋ค.
- ์ด๋ ๋๋ผ์ด๋น ํ ์ด๋ธ์ ๋ ์ฝ๋ ๊ฑด๋ณ๋ก ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์ฐพ์ผ๋ฉด ๋ ์ฝ๋๋ฅผ ์ฐพ๊ณ ์ฝ๋ ์คํ ๋ฆฌ์ง ์์ง์์๋ ์๋ฌด๋ฐ ์ต์ ํ๋ฅผ ์ํํ ์๊ฐ ์๋ค.
- ์ด๋ฅผ
- ์ด ๊ฐ์ ๋จ์ ์ ๋ณด์ํ๊ธฐ ์ํด MySQL ์๋ฒ๋ ์กฐ์ธ ๋์ ํ
์ด๋ธ ์ค ํ๋๋ก๋ถํฐ ๋ ์ฝ๋๋ฅผ ์ฝ์ด์ ์กฐ์ธ ๋ฒํผ์ ๋ฒํผ๋งํ๋ค.
- ๋๋ผ์ด๋น ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์ฝ์ด์ ๋๋ฆฌ๋ธ ํ ์ด๋ธ๊ณผ์ ์กฐ์ธ์ ์ฆ์ ์คํํ์ง ์๊ณ ์กฐ์ธ ๋์์ ๋ฒํผ๋งํ๋ ๊ฒ์ด๋ค.
- ์กฐ์ธ ๋ฒํผ์ ๋ ์ฝ๋๊ฐ ๊ฐ๋ ์ฐจ๋ฉด MySQL ์์ง์ ๋ฒํผ๋ง๋ ๋ ์ฝ๋๋ฅผ ์คํ ๋ฆฌ์ง ์์ง์ผ๋ก ํ ๋ฒ์ ์์ฒญํ๋ค.
- ์ด๋ฅผ ํตํด ์คํ ๋ฆฌ์ง ์์ง์ ์ฝ์ด์ผํ ๋ ์ฝ๋๋ค์ ๋ฐ์ดํฐ ํ์ด์ง์ ์ ๋ ฌ๋ ์์๋ก ์ ๊ทผํด์ ๋์คํฌ์ ๋ฐ์ดํฐ ํ์ด์ง ์ฝ๊ธฐ๋ฅผ ์ต์ํํ ์ ์๋ ๊ฒ์ด๋ค.
- ๋ฌผ๋ก ๋ฐ์ดํฐ ํ์ด์ง๊ฐ ๋ฉ๋ชจ๋ฆฌ(InnoDB ๋ฒํผ ํ)์ ์๋ค๊ณ ํ๋๋ผ๋ ๋ฒํผ ํ์ ์ ๊ทผ์ ์ต์ํํ ์ ์๋ ๊ฒ์ด๋ค.
- MMR์ ์์ฉํด์ ์คํ๋๋ ์กฐ์ธ ๋ฐฉ์์ธ BKA ์กฐ์ธ ์ต์ ํ ๋ฐฉ์๋ ์๋๋ฐ ๊ธฐ๋ณธ๊ฐ์ด
off์ด๋ค.- ๊ทธ ์ด์ ๋ BKA ์กฐ์ธ์ ์ฌ์ฉํ๋ฉด ๋ถ๊ฐ์ ์ธ ์ ๋ ฌ ์์ ์ด ํ์ํด์ง๊ธฐ ๋๋ฌธ์ ์คํ๋ ค ์ฑ๋ฅ์ด ์ ์ข์์ง ์ ์๋ค๋ ๋จ์ ์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค.
- ํ์ง๋ง ๋์์ด ๋๋ ๊ฒฝ์ฐ๋ ์๋ค.
MySQL 8.0.18 ๋ฒ์ ๋ถํฐ ํด์ ์กฐ์ธ ์๊ณ ๋ฆฌ์ฆ์ด ๋์ ๋์๊ณ , MySQL 8.0.20 ๋ฒ์ ๋ถํฐ๋ ๋ธ๋ก ๋ค์คํฐ๋ ์กฐ์ธ์ ๋์ด์ ์ฌ์ฉ๋์ง ์๊ณ ํด์ ์กฐ์ธ ์๊ณ ๋ฆฌ์ฆ์ ๋์ฒด๋๋ค. ๋ฐ๋ผ์ Extra ์นผ๋ผ์ "Using Join Buffer(block nested loop)" ๋ฉ์์ง๊ฐ ํ์๋์ง ์์ ์ ์๋ค.
- MySQL์์ ์ฌ์ฉ๋๋ ๋๋ถ๋ถ์ ์กฐ์ธ์ด ๋ค์คํฐ๋ ๋ฃจํ ์กฐ์ธ์ด๋ค.
- ์กฐ์ธ์ ์ฐ๊ฒฐ ์กฐ๊ฑด์ด ๋๋ ์นผ๋ผ์ ๋ชจ๋ ์ธ๋ฑ์ค๊ฐ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ๋๋ ์กฐ์ธ ๋ฐฉ์์ด๋ค.
- ๋ง์น ์ค์ฒฉ๋ ๋ฐ๋ณต ๋ช ๋ น์ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ์๋ํ๋ค๊ณ ํ์ฌ ๋ค์คํฐ๋ ๋ฃจํ ์กฐ์ธ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
mysql> EXPLAIN
SELECT *
FROM employees e
INNER JOIN salaries s ON s.emp_no = e.emp_no
AND s.from_date <= NOW()
AND s.to_date >= NOW()
WHERE e.first_name = 'Amor';
+----+-------------+------+--------------+------+----------+-------------+
| id | select_type | type | key | rows | filtered | Extra |
+----+-------------+------+--------------+------+----------+-------------+
| 1 | SIMPLE | ref | ix_firstname | 1 | 100.00 | NULL |
| 1 | SIMPLE | ref | PRIMARY | 9 | 11.11 | Using where |
+----+-------------+------+--------------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)- ๋ค์คํฐ๋ ๋ฃจํ ์กฐ์ธ๊ณผ ๋ธ๋ก ๋ค์คํฐ๋ ๋ฃจํ ์กฐ์ธ(Block Nested Loop Join)์ ๊ฐ์ฅ ํฐ ์ฐจ์ด๋ ์กฐ์ธ ๋ฒํผ๊ฐ ์ฌ์ฉ๋๋์ง ์ฌ๋ถ์ ์กฐ์ธ์์ ๋๋ผ์ด๋น ํ ์ด๋ธ๊ณผ ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ด ์ด๋ค ์์๋ก ์กฐ์ธ๋๋๋์ด๋ค.
- ์กฐ์ธ ์๊ณ ๋ฆฌ์ฆ์์ "Block"์ด๋ผ๋ ๋จ์ด๊ฐ ์ฌ์ฉ๋๋ฉด ์กฐ์ธ์ฉ์ผ๋ก ๋ณ๋์ ๋ฒํผ๊ฐ ์ฌ์ฉ๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋๋ฐ, ์กฐ์ธ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์์ Extra ์นผ๋ผ์ "Using Join buffer"๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ํ์๋๋ฉด ๊ทธ ์คํ ๊ณํ์ ์กฐ์ธ ๋ฒํผ๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
- ์กฐ์ธ์ ๋๋ผ์ด๋น ํ
์ด๋ธ์์ ์ผ์นํ๋ ๋ ์ฝ๋์ ๊ฑด์๋งํผ ๋๋ฆฌ๋ธ ํ
์ด๋ธ์ ๊ฒ์ํ๋ฉด์ ์ฒ๋ฆฌ๋๋ค. ๋๋ผ์ด๋น ํ
์ด๋ธ์ ํ ๋ฒ์ ์ญ ์ฝ์ง๋ง, ๋๋ฆฌ๋ธ ํ
์ด๋ธ์ ์ฌ๋ฌ ๋ฒ ์ฝ๋๋ค.
- ex) ๋๋ผ์ด๋น ํ ์ด๋ธ์ ์ผ์นํ๋ ๋ ์ฝ๋ 1,000๊ฑด. ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ ์กฐ์ธ ์กฐ๊ฑด์ด ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ ์ ์์๋ค๋ฉด ๋๋ฆฌ๋ธ ํ ์ด๋ธ์์ ์ฐ๊ฒฐ๋๋ ๋ ์ฝ๋๋ฅผ ์ฐพ๊ธฐ ์ํด 1,000๋ฒ์ ํ ํ ์ด๋ธ ์ค์บ์ ํด์ผ ํ๋ค.
- ๊ทธ๋์ ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ ๊ฒ์ํ ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ฟผ๋ฆฌ๋ ์๋นํ ๋๋ ค์ง๋ฉฐ, ์ตํฐ๋ง์ด์ ๋ ์ต๋ํ ๋๋ฆฌ๋ธ ํ ์ด๋ธ์ ๊ฒ์์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ์คํ ๊ณํ์ ์๋ฆฝํ๋ค.
- ๊ทธ๋ฐ๋ฐ ์ด๋ค ๋ฐฉ์์ผ๋ก๋ ๋๋ฆฌ๋ธ ํ
์ด๋ธ์ ํ ํ
์ด๋ธ ์ค์บ์ด๋ ์ธ๋ฑ์ค ํ ์ค์บ์ ํผํ ์ ์๋ค๋ฉด ์ตํฐ๋ง์ด์ ๋ ๋๋ผ์ด๋น ํ
์ด๋ธ์์ ์ฝ์ ๋ ์ฝ๋๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์บ์ํ ํ ๋๋ฆฌ๋ธ ํ
์ด๋ธ๊ณผ ์ด ๋ฉ๋ชจ๋ฆฌ ์บ์๋ฅผ ์กฐ์ธํ๋ ํํ๋ก ์ฒ๋ฆฌํ๋ค.
- ์ด ๋ ์ฌ์ฉ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ์บ์๋ฅผ
์กฐ์ธ ๋ฒํผ Join Buffer๋ผ๊ณ ํ๋ค. - ์กฐ์ธ ๋ฒํผ๋
join_buffer_size๋ผ๋ ์์คํ ๋ณ์๋ก ํฌ๊ธฐ๋ฅผ ์ ํํ ์ ์์ผ๋ฉฐ ์กฐ์ธ์ด ์๋ฃ๋๋ฉด ์กฐ์ธ ๋ฒํผ๋ ๋ฐ๋ก ํด์ ๋๋ค.
- ์ด ๋ ์ฌ์ฉ๋๋ ๋ฉ๋ชจ๋ฆฌ์ ์บ์๋ฅผ
- ์๋ ์กฐ์ธ์ ์์ ๋ ๊ฐ ํ
์ด๋ธ์ ๋ํ ์กฐ๊ฑด
WHERE๋ ์์ง๋ง, ๋ ํ ์ด๋ธ ๊ฐ์ ์ฐ๊ฒฐ ๊ณ ๋ฆฌ ์ญํ ์ ํ๋ ์กฐ์ธ ์กฐ๊ฑด์ ์๋ค.- ๋ฐ๋ผ์
dept_empํ ์ด๋ธ์์from_date>'2000-01-01'์ธ ๋ ์ฝ๋(10,616๊ฑด)์employeesํ ์ด๋ธ์์emp_no<109004์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋(99,003๊ฑด)๋ ์นดํ ์์ ์กฐ์ธ์ ์ํํ๋ค.
- ๋ฐ๋ผ์
mysql> EXPLAIN
SELECT *
FROM dept_emp de, employees e
WHERE de.from_date > '1995-01-01' AND e.emp_no < 109004;
+----+-------------+-------+-------+---------+--------+----------+--------------------------------------------+
| id | select_type | table | type | key | rows | filtered | Extra |
+----+-------------+-------+-------+---------+--------+----------+--------------------------------------------+
| 1 | SIMPLE | e | range | PRIMARY | 150070 | 100.00 | Using where |
| 1 | SIMPLE | de | ALL | NULL | 331143 | 50.00 | Using where; Using join buffer (hash join) |
+----+-------------+-------+-------+---------+--------+----------+--------------------------------------------+
2 rows in set, 1 warning (0.01 sec)- ์คํ ๊ณํ์ ์ดํด๋ณด๋ฉด "Using Join Buffer(block nested loop)" ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋์ง ์๊ณ "Using Join Buffer(hash join)"์ผ๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
- ์ฃผ์์์ ๋ณด์ฌ์ค ๊ฒ์ฒ๋ผ ํด์ ์กฐ์ธ ์๊ณ ๋ฆฌ์ฆ์ด ๋์ ๋๊ธฐ ๋๋ฌธ์ด๋ค. 8.0.20 ๋ฒ์ ์ด์ ์ด๋ผ๋ฉด "Using join buffer (block nested loop)"๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ์ถ๋ ฅ๋์ ๊ฒ์ด๋ค.
- ์ ์ฟผ๋ฆฌ๋ ์๋์ ๊ณผ์ ์ ๊ฑฐ์ณ ์คํ๋๋ค. (block nested loop join์ ๊ฒฝ์ฐ)
dept_empํ ์ด๋ธ์ix_fromdate์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด(from_date > '1995-01-01') ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋๋ฅผ ๊ฒ์ํ๋ค.- ์กฐ์ธ์ ํ์ํ ๋๋จธ์ง ์นผ๋ผ์ ๋ชจ๋
dept_empํ ์ด๋ธ๋ก๋ถํฐ ์ฝ์ด์ ์กฐ์ธ ๋ฒํผ์ ์ ์ฅํ๋ค. employeesํ ์ด๋ธ์ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ ์ด์ฉํด (emp_no < 109004) ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋๋ฅผ ๊ฒ์ํ๋ค.- 3๋ฒ์์ ๊ฒ์๋ ๊ฒฐ๊ณผ(
employees)์ 2๋ฒ์ ์บ์๋ ์กฐ์ธ ๋ฒํผ์ ๋ ์ฝ๋(dept_emp)๋ฅผ ๊ฒฐํฉํด์ ๋ฐํํ๋ค.
- MySQL 5.6 ๋ฒ์ ๋ถํฐ ๋์ ๋ ๊ธฐ๋ฅ, ์ฟผ๋ฆฌ์ ์ฑ๋ฅ์ ๋ช ๋ฐฐ์์ ๋ช์ญ ๋ฐฐ๋ก ํฅ์ํ ์ ์๋ ์ค์ํ ๊ธฐ๋ฅ์ด๋ค.
- ์๋์ ๊ฐ์ด ์ค์ ํด์ค ์ ์๋ค. (๊ธฐ๋ณธ๊ฐ์
on์ด๋ค.)
# on
mysql> SET optimizer_switch='index_condition_pushdown=on';
# off
mysql> SET optimizer_switch='index_condition_pushdown=off';- ๋จผ์ ๋นํ์ฑํํด์ ํ ์คํธ๋ฅผ ์งํํด๋ณด์.
mysql> ALTER TABLE employees ADD INDEX ix_lastname_firstname (last_name, first_name);
Query OK, 0 rows affected (0.67 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SET optimizer_switch='index_condition_pushdown=off';
mysql> SHOW VARIABLES LIKE 'optimizer_switch' \G
*************************** 1. row ***************************
Variable_name: optimizer_switch
Value: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,use_invisible_indexes=off,skip_scan=on,hash_join=on,subquery_to_derived=off,prefer_ordering_index=on,hypergraph_optimizer=off,derived_condition_pushdown=on
1 row in set (0.00 sec)- ์ด์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋ ์คํ ๋ฆฌ์ง ์์ง์ด ๋ช ๊ฑด์ ๋ ์ฝ๋๋ฅผ ์ฝ๋์ง๋ฅผ ์ดํด๋ณด์.
mysql> EXPLAIN
SELECT * FROM employees WHERE last_name='Acton' AND first_name LIKE '%sal';
+----+-------------+-----------+------+-----------------------+---------+------+----------+-------------+
| id | select_type | table | type | key | key_len | rows | filtered | Extra |
+----+-------------+-----------+------+-----------------------+---------+------+----------+-------------+
| 1 | SIMPLE | employees | ref | ix_lastname_firstname | 66 | 189 | 11.11 | Using where |
+----+-------------+-----------+------+-----------------------+---------+------+----------+-------------+-
"Using where"๋ผ๊ณ ํ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
- "Using where"๋ InnoDB ์คํ ๋ฆฌ์ง ์์ง์ด ์ฝ์ด์ ๋ฐํํด์ค ๋ ์ฝ๋๊ฐ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋
WHERE์กฐ๊ฑด์ ์ผ์นํ๋์ง ๊ฒ์ฌํ๋ ๊ณผ์ ์ ์๋ฏธํ๋ค. - ์ด ์ฟผ๋ฆฌ์์๋
first_name LIKE '%sal'์ด ๊ฒ์ฌ ๊ณผ์ ์์ ์ฌ์ฉ๋ ์กฐ๊ฑด์ด๋ค.
- "Using where"๋ InnoDB ์คํ ๋ฆฌ์ง ์์ง์ด ์ฝ์ด์ ๋ฐํํด์ค ๋ ์ฝ๋๊ฐ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋
-
์๋ ๊ทธ๋ฆผ์
last_name='Anton'์กฐ๊ฑด์ผ๋ก ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ์ ํ๊ณ ํ ์ด๋ธ์ ๋ ์ฝ๋๋ฅผ ์ฝ์ ํ,first_name LIKE '%sal'์กฐ๊ฑด์ ๋ถํฉํ๋์ง ์ฌ๋ถ๋ฅผ ๋น๊ตํ๋ ๊ณผ์ ์ ํํํ ๊ฒ์ด๋ค.- ์ฑ๋ฅ๊ณผ ํฐ ๊ด๊ณ๊ฐ ์์ด ๋ณด์ผ ์ ์์ง๋ง, ์ฌ์ค ์ด ๊ณผ์ ์ ๋งค์ฐ ์ค์ํ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ค.
- ์ค์ ํ
์ด๋ธ์ ์ฝ์ด์ 3๊ฑด์ ๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์์ง๋ง ๊ทธ์ค ๋จ 1๊ฑด๋ง
first_name LIKE '%sal'์กฐ๊ฑด์ ์ผ์นํ๋ค. - ๊ทธ๋ฐ๋ฐ ๋ง์ฝ
last_name์กฐ๊ฑด์ ์ผ์นํ๋ ๋ ์ฝ๋๊ฐ 10๋ง ๊ฑด์ด๊ณ , ๊ทธ์ค์์first_name์กฐ๊ฑด์ ์ผ์นํ๋ ๊ฒฝ์ฐ๊ฐ ๋จ 1๊ฑด๋ง ์๋ค๋ฉด ์ด๋จ๊น? => 99,999๊ฑด์ ๋ ์ฝ๋ ์ฝ๊ธฐ๊ฐ ๋ถํ์ํ ์์ ์ด ๋๋ค.
- MySQL 5.6 ๋ฒ์ ๋ถํฐ๋ ์ด๋ ๊ฒ ์ธ๋ฑ์ค๋ฅผ ๋ฒ์ ์ ํ ์กฐ๊ฑด์ผ๋ก ์ฌ์ฉํ์ง ๋ชปํ๋ค๊ณ ํ๋๋ผ๋ ์ธ๋ฑ์ค์ ํฌํจ๋ ์กฐ๊ฑด์ด ์๋ค๋ฉด ๋ชจ๋ ๋ชจ์์ ์คํ ๋ฆฌ์ง ์์ง์ผ๋ก ์ ๋ฌํ ์ ์๊ฒ ํธ๋ค๋ฌ API๊ฐ ๊ฐ์ ๋๋ค.
- ๋ฐ๋ผ์ ์๋์ ๊ฐ์ด ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ์ต๋ํ ํํฐ๋ง๊น์ง ์๋ฃํด์ ๊ผญ ํ์ํ ๋ ์ฝ๋ 1๊ฑด์ ๋ํด์๋ง ํ ์ด๋ธ ์ฝ๊ธฐ๋ฅผ ์ํํ ๊ฒ์ด๋ค.
- ์คํ๊ณํ์ ํ์ธํด๋ณด๋ฉด "Using where"์ด ์๋๋ผ "Using index condition"์ด๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
SET optimizer_switch='index_condition_pushdown=on';
mysql> EXPLAIN
SELECT * FROM employees WHERE last_name='Acton' AND first_name LIKE '%sal';
+----+-------------+-----------+------+-----------------------+---------+------+----------+-----------------------+
| id | select_type | table | type | key | key_len | rows | filtered | Extra |
+----+-------------+-----------+------+-----------------------+---------+------+----------+-----------------------+
| 1 | SIMPLE | employees | ref | ix_lastname_firstname | 66 | 189 | 11.11 | Using index condition |
+----+-------------+-----------+------+-----------------------+---------+------+----------+-----------------------+- InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ์ฌ์ฉํ๋ ํ ์ด๋ธ์์ ์ธ์ปจ๋๋ฆฌ ์ธ๋ฑ์ค์ ์๋์ผ๋ก ์ถ๊ฐ๋ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ ํ์ฉํ ์ ์๊ฒ ํ ์ง๋ฅผ ๊ฒฐ์ ํ๋ ์ต์
- "์ธ์ปจ๋๋ฆฌ ์ธ๋ฑ์ค์ ์๋์ผ๋ก ์ถ๊ฐ๋ ํ๋ผ์ด๋จธ๋ฆฌ ํค"์ ์๋ฏธ์ ์ด๋ก ์ธํ ์ฑ๋ฅ์์ ์ฅ์ ?
- InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ ํด๋ฌ์คํฐ๋ง ํค๋ก ์์ฑํ๋ค. ๊ทธ๋์ ๋ชจ๋ ์ธ์ปจ๋๋ฆฌ ์ธ๋ฑ์ค๋ ๋ฆฌํ ๋
ธ๋์ ํ๋ผ์ด๋จธ๋ฆฌ ํค ๊ฐ์ ๊ฐ์ง๋ค.
- ์๋ฅผ ๋ค์ด ํ๋ผ์ด๋จธ๋ฆฌ ํค๊ฐ
(dept_no, emp_no)์ ๊ฐ์ด ๋์ด ์๋ ํ ์ด๋ธ์from_date์นผ๋ผ์ ๋ํด ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ฉด(dept_no, emp_no, from_date)์กฐํฉ์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ๊ฒ๊ณผ ํก์ฌํ๊ฒ ์๋ํ๋ค๋ ์๋ฏธ์ด๋ค.
- ์๋ฅผ ๋ค์ด ํ๋ผ์ด๋จธ๋ฆฌ ํค๊ฐ
- MySQL ์๋ฒ๊ฐ ์
๊ทธ๋ ์ด๋ ๋๋ฉด์ ์ตํฐ๋ง์ด์ ๋
ix_fromdate์ธ๋ฑ์ค์ ๋ง์ง๋ง์(dept_no, emp_no)์นผ๋ผ์ด ์จ์ด์๋ค๋ ๊ฒ์ ์ธ์งํ๊ณ ์คํ ๊ณํ์ ์๋ฆฝํ๋๋ก ๊ฐ์ ๋๋ค.- ์์ ๋ฒ์ ์ MySQL ๋ฒ์ ์์๋ ์๋์ ๊ฐ์ ์ฟผ๋ฆฌ๊ฐ ์ธ์ปจ๋๋ฆฌ ์ธ๋ฑ์ค์ ๋ง์ง๋ง์ ์๋ ์ถ๊ฐ๋๋ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ ์ ๋๋ก ํ์ฉํ์ง ๋ชปํ์๋ค.
mysql> EXPLAIN SELECT COUNT(*) FROM dept_emp WHERE from_date='1987-07-25' AND dept_no='d001';
+----+-------------+----------+------+-------------+---------+-------------+
| id | select_type | table | type | key | key_len | Extra |
+----+-------------+----------+------+-------------+---------+-------------+
| 1 | SIMPLE | dept_emp | ref | ix_fromdate | 19 | Using index |
+----+-------------+----------+------+-------------+---------+-------------+- ์คํ ๊ณํ์
key_len์นผ๋ผ์ ์ด ์ฟผ๋ฆฌ๊ฐ ์ธ๋ฑ์ค๋ฅผ ๊ตฌ์ฑํ๋ ์นผ๋ผ ์ค์์ ์ด๋ ๋ถ๋ถ(์ด๋ ์นผ๋ผ)๊น์ง ์ฌ์ฉํ๋์ง๋ฅผ ๋ฐ์ดํธ ์๋ก ๋ณด์ฌ์ฃผ๋๋ฐ, ์ด ์์ ์์๋ 19๋ฐ์ดํธ๊ฐ ํ์๋์๋ค.- ์ด๋
from_date์นผ๋ผ(3๋ฐ์ดํธ)๊ณผdept_emp์นผ๋ผ(16๋ฐ์ดํธ)๊น์ง ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์ ์ถํด๋ณผ ์ ์๋ค.
- ์ด๋
mysql> EXPLAIN SELECT COUNT(*) FROM dept_emp WHERE from_date='1987-07-25';
+----+-------------+----------+------+-------------+---------+-------------+
| id | select_type | table | type | key | key_len | Extra |
+----+-------------+----------+------+-------------+---------+-------------+
| 1 | SIMPLE | dept_emp | ref | ix_fromdate | 3 | Using index |
+----+-------------+----------+------+-------------+---------+-------------+- ๋ฐ๋ฉด "dept_no='d001'" ์กฐ๊ฑด์ ์ ๊ฑฐํ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์์๋ ์์ ๊ฐ์ด
from_date์นผ๋ผ์ ์ํ 3๋ฐ์ดํธ๋ง ํ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.- from_date์ DATE ํ์ (3byte)์ด๋ค.
- ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ ๊ฒฝ์ฐ, ๋๋ถ๋ถ ์ตํฐ๋ง์ด์ ๋ ํ ์ด๋ธ ๋ณ๋ก ํ๋์ ์ธ๋ฑ์ค๋ง ์ฌ์ฉํ๋๋ก ์คํ๊ณํ์ ์๋ฆฝํ๋ค.
- ํ์ง๋ง ์ธ๋ฑ์ค ๋จธ์ง ์คํ ๊ณํ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ๋์ ํ ์ด๋ธ์ ๋ํด 2๊ฐ ์ด์์ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ์ฟผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ๋ค.
- ๋ณดํต ์ธ๋ฑ์ค๋ฅผ ํ๋๋ง ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์จ์ ์ด๋ ์ฌ์ฉ๋ ๊ฐ๊ฐ์ ์กฐ๊ฑด์ด ์๋ก ๋ค๋ฅธ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ณ ๊ทธ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ์ฝ๋ ๊ฑด์๊ฐ ๋ง์ ๊ฒ์ผ๋ก ์์๋ ๋ MySQL ์๋ฒ๋ ์ธ๋ฑ์ค ๋จธ์ง ์คํ ๊ณํ์ ์ ํํ๋ค.
- ์ธ๋ฑ์ค ๋จธ์ง ์คํ ๊ณํ์ 3๊ฐ์ ์ธ๋ถ ์คํ ๊ณํ์ผ๋ก ๋๋ ๋ณผ ์ ์๋ค. 3๊ฐ์ง ์ต์ ํ ๋ชจ๋ ์ฌ๋ฌ ๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์จ๋ค๋ ๊ฒ์ ๋์ผํ์ง๋ง ๊ฐ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ณํฉํ ์ง์ ๋ฐ๋ผ ๊ตฌ๋ถ๋๋ค.
index_merge_intersectionindex_merge_sort_unionindex_merge_union
index_merge์ตํฐ๋ง์ด์ ์ต์ ๋ ์กด์ฌํ๋๋ฐ, ์์ 3๊ฐ์ ์ต์ ํ ์ต์ ์ ํ ๋ฒ์ ์ ์ดํ ์ ์๋ ์ต์ ์ด๋ค.
- ์๋์ ์์๋ฅผ ๋ณด์.
first_name์ix_firstname์ธ๋ฑ์คemp_no๋PRIMARY์ธ๋ฑ์ค
mysql> EXPLAIN
SELECT *
FROM employees
WHERE first_name='Georgi' AND emp_no BETWEEN 10000 AND 20000;
+-------------+----------------------+---------+------+----------------------------------------------------+
| type | key | key_len | rows | Extra |
+-------------+----------------------+---------+------+----------------------------------------------------+
| index_merge | ix_firstname,PRIMARY | 62,4 | 1 | Using intersect(ix_firstname,PRIMARY); Using where |
+-------------+----------------------+---------+------+----------------------------------------------------+
1 row in set, 1 warning (0.01 sec)- 2๊ฐ์ ์ธ๋ฑ์ค ์ค ์ด๋ค ์กฐ๊ฑด์ ์ฌ์ฉํ๋๋ผ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- ์ตํฐ๋ง์ด์ ๋ 2๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ๋ชจ๋ ์ฌ์ฉํด์ ์ฟผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
- Extra์ "Using intersect(ix_firstname,PRIMARY)"๋ผ๊ณ ๋ณด์ด๋ ๊ฒ์ด ์ธ๋ฑ์ค๋ฅผ ๊ฐ๊ฐ ๊ฒ์ํด์ ๊ทธ ๊ฒฐ๊ณผ์ ๊ต์งํฉ๋ง ๋ฐํํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ ๊ฒ์ด๋ค.
- ๋ ๊ฐ์ง ์กฐ๊ฑด ์ค ํ๋๋ผ๋ ์ถฉ๋ถํ ํจ์จ์ ์ผ๋ก ์ฟผ๋ฆฌ๋ฅด ์ฒ๋ฆฌํ ์ ์์๋ค๋ฉด ์ตํฐ๋ง์ด์ ๋ 2๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ๋ชจ๋ ์ฌ์ฉํ๋ ์คํ ๊ณํ์ ์ฌ์ฉํ์ง ์์์ ๊ฒ์ด๋ค.
- ์ฆ, ์ตํฐ๋ง์ด์ ๋ ๊ฐ๊ฐ์ ์กฐ๊ฑด์ ์ผ์นํ๋ ๋ ์ฝ๋ ๊ฑด์๋ฅผ ์์ธกํด ๋ณธ ๊ฒฐ๊ณผ, ๋ ์กฐ๊ฑด ๋ชจ๋ ์๋์ ์ผ๋ก ๋ง์ ๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ค๋ ๊ฒ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
mysql> SELECT COUNT(*) FROM employees WHERE first_name='Georgi';
+----------+
| COUNT(*) |
+----------+
| 253 |
+----------+
mysql> SELECT COUNT(*) FROM employees WHERE emp_no BETWEEN 10000 AND 20000;
+----------+
| COUNT(*) |
+----------+
| 10000 |
+----------+- ๋ง์ฝ ์ธ๋ฑ์ค ๋จธ์ง ์คํ ๊ณํ์ด ์๋์๋ค๋ฉด 2๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํด์ผ ํ์ ๊ฒ์ด๋ค.
- "first_name='Georgi'" ์กฐ๊ฑด๋ง ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ผ์นํ๋ ๋ ์ฝ๋ 253๊ฑด์ ๊ฒ์ํ ๋ค์ ๋ฐ์ดํฐ ํ์ด์ง์์ ๋ ์ฝ๋๋ฅผ ์ฐพ๊ณ
emp_no์นผ๋ผ์ ์กฐ๊ฑด์ ์ผ์นํ๋ ๋ ์ฝ๋๋ค๋ง ๋ฐํํ๋ ํํ๋ก ์ฒ๋ฆฌ๋ผ์ผ ํ๋ค. - "emp_no BETWEEN 10000 AND 20000" ์กฐ๊ฑด๋ง ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ ์ด์ฉํด 10,000๊ฑด์ ์ฝ์ด์์ "first_name='Georgi'" ์กฐ๊ฑด์ ์ผ์นํ๋ ๋ ์ฝ๋๋ง ๋ฐํํ๋ ํํ๋ก ์ฒ๋ฆฌ๋ผ์ผ ํ๋ค.
- ๋ฐ๋ฉด ๋ ์กฐ๊ฑด์ ๋ชจ๋ ๋ง์กฑํ๋ ๋ ์ฝ๋ ๊ฑด์๋ 14๊ฑด๋ฐ์ ์๋๋ค.
- ์์ ๋ ์กฐ๊ฑด์์ ๊ฒฐ๊ตญ ์๋ฏธ ์๋ ์กฐํ๋ ์ ์ฒด ์ค 14๊ฑด๋ง ์๋ค๋ ๋ป์ด๋ค. => ๋นํจ์จ์ด ํฐ ์ํฉ์ด์๊ธฐ ๋๋ฌธ์ ์ตํฐ๋ง์ด์ ๋ ๊ฐ ์ธ๋ฑ์ค๋ฅผ ๊ฒ์ํด ๋ ๊ฒฐ๊ณผ์ ๊ต์งํฉ๋ง ์ฐพ์์ ๋ฐํํ ๊ฒ์ด๋ค.
mysql> SELECT COUNT(*) FROM employees
WHERE first_name='Georgi' AND emp_no BETWEEN 10000 AND 20000;
+----------+
| COUNT(*) |
+----------+
| 14 |
+----------+ix_firstname์ธ๋ฑ์ค๋ ํ๋ผ์ด๋จธ๋ฆฌ ํค์ธemp_no์นผ๋ผ์ ์๋์ผ๋ก ํฌํจํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅix_firstname์ธ๋ฑ์ค๋ง ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ฑ๋ฅ์ด ์ข์ ๊ฒ์ผ๋ก ์๊ฐํ ์๋ ์๋ค.- ๊ทธ๋ ๋ค๋ฉด ์๋์ ๊ฐ์ด
index_merge_intersection์ ๋นํ์ฑํํด๋ผ. - ์๋ฒ ์ ์ฒด์ ์ผ๋ก ํ๋ ๊ฒ์ด ๋ถ์ํ๋ค๋ฉด ํ์ฌ ์ปค๋ฅ์ ๋๋ ํ์ฌ ์ฟผ๋ฆฌ์ ๋ํด์๋ง ์ต์ ํ๋ฅผ ๋นํ์ฑํํ๋ ๊ฒ๋ ๋ฐฉ๋ฒ์ด๋ค.
- ๊ทธ๋ ๋ค๋ฉด ์๋์ ๊ฐ์ด
mysql> SET GLOBAL optimizer_switch='index_merge_intersection=off';- ์ธ๋ฑ์ค ๋จธ์ง์ 'Using union'์ WHERE ์ ์ ์ฌ์ฉ๋ 2๊ฐ ์ด์์ ์กฐ๊ฑด์ด ๊ฐ๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋
OR์ฐ์ฐ์๋ก ์ฐ๊ฒฐ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉ๋๋ ์ต์ ํ๋ค. - ์์
first_name์นผ๋ผ์ix_firstname์ธ๋ฑ์คhire_date์นผ๋ผ์ix_hiredate์ธ๋ฑ์ค
mysql> EXPLAIN
SELECT * FROM employees
WHERE first_name='Matt' OR hire_date='1987-03-31';
+-------------+--------------------------+---------+------+----------------------------------------------------+
| type | key | key_len | rows | Extra |
+-------------+--------------------------+---------+------+----------------------------------------------------+
| index_merge | ix_firstname,ix_hiredate | 58,3 | 344 | Using union(ix_firstname,ix_hiredate); Using where |
+-------------+--------------------------+---------+------+----------------------------------------------------+- "Using union(ix_firstname,ix_hiredate)"์ด๋ผ๊ณ ํ์๋์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
- ์ธ๋ฑ์ค ๋จธ์ง ์ต์ ํ๊ฐ
ix_firstname๊ณผix_hiredate์ธ๋ฑ์ค ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ Union ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ณํฉํ๋ค๋ ๊ฒ์ ์๋ฏธ์ด๋ค. (ํฉ์งํฉ)
- ์ธ๋ฑ์ค ๋จธ์ง ์ต์ ํ๊ฐ
- MySQL ์๋ฒ๋ ๋ ๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ํตํ ๊ฒฐ๊ณผ์ ์งํฉ์ ์ ๋ ฌํด ์ค๋ณต ๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ ์์ ์ ์ํํ๋ค.
- ๋ ๊ฐ์ ์งํฉ์ ํ๋ผ์ด๋จธ๋ฆฌํค(
emp_no)๋ก ์ ๋ ฌ๋์ด ์๊ธฐ ๋๋ฌธ์ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ก ์ ๋ ฌํ์ฌemp_no์นผ๋ผ์ด ์ค๋ณต๋ ๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๊ณ ํ๋์ ๋ ์ฝ๋๋ง ๋ด๋ณด๋ธ๋ค. - ์ค๋ณต ์ ๊ฑฐ๋ฅผ ํ ๋ ์ฌ์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฐ์ ์์ ํ(Priority Queue)์ด๋ค.
- ์ฌ์ค SQL ๋ฌธ์ฅ์์ AND ์ฐ์ฐ์์ OR ์ฐ์ฐ์๋ ์๋นํ ํฐ ์ฐจ์ด๋ฅผ ๋ณด์ธ๋ค. 2๊ฐ์ ์กฐ๊ฑด์ด AND๋ก ์ฐ๊ฒฐ๋ ๊ฒฝ์ฐ์๋ ๋ ์กฐ๊ฑด ์ค ํ๋๋ผ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉด ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ์ผ๋ก ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ค.
- ํ์ง๋ง 2๊ฐ์ WHERE ์กฐ๊ฑด์ด OR ์ฐ์ฐ์๋ก ์ฐ๊ฒฐ๋ ๊ฒฝ์ฐ์๋ ๋ ์ค ํ๋๋ผ๋ ์ ๋๋ก ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ฉด ํญ์ ํ ํ ์ด๋ธ ์ค์บ์ผ๋ก๋ฐ์ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ค.
- ๋ง์ฝ ์ธ๋ฑ์ค ๋จธ์ง ์์ ์ ํ๋ ๋์ค์ ๊ฒฐ๊ณผ์ ์ ๋ ฌ์ด ํ์ํ ๊ฒฝ์ฐ MySQL ์๋ฒ๋ ์ธ๋ฑ์ค ๋จธ์ง ์ต์ ํ์ 'Sort Union' ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ค.
mysql> EXPLAIN
SELECT * FROM employees
WHERE first_name='Matt'
OR hire_date BETWEEN '1987-03-01' AND '1987-03-31';
+-------------+--------------------------+---------+------+---------------------------------------------------------+
| type | key | key_len | rows | Extra |
+-------------+--------------------------+---------+------+---------------------------------------------------------+
| index_merge | ix_firstname,ix_hiredate | 58,3 | 3197 | Using sort_union(ix_firstname,ix_hiredate); Using where |
+-------------+--------------------------+---------+------+---------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)- ์์ ์์ ๋ฅผ
Union์๊ณ ๋ฆฌ์ฆ ์ค๋ช ๊ณผ ๊ฐ์ด 2๊ฐ์ ์ฟผ๋ฆฌ๋ก ๋ถ๋ฆฌํด ์๊ฐํด๋ณด์.
mysql> SELECT * FROM employees WHERE first_name='Matt';
mysql> SELECT * FROM employees WHERE hire_date BETWEEN '1987-03-01' AND '1987-03-31';first_name='Matt'์ ์ emp_no๋ก ์ ๋ ฌ๋์ด ์ถ๋ ฅ๋์ง๋งhire_date BETWEEN '1987-03-01' AND '1987-03-31'์กฐ๊ฑด์ix_hiredateindex ์์๋๋ก ์ ๋ ฌ๋์ด ์๊ธฐ ๋๋ฌธ์ emp_no ์นผ๋ผ์ผ๋ก ์ ๋ ฌ๋์ง ์๋๋ค.- ์ฆ, ์ ์์ ์ ๊ฒฐ๊ณผ์์๋ ์ค๋ณต์ ์ ๊ฑฐํ๊ธฐ ์ํด ์ฐ์ ์์ ํ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๋ค.
- ๊ทธ๋์ MySQL ์๋ฒ๋ ๋ ์งํฉ์ ๊ฒฐ๊ณผ์์ ์ค๋ณต์ ์ ๊ฑฐํ๊ธฐ ์ํด ๊ฐ ์งํฉ์
emp_no์นผ๋ผ์ผ๋ก ์ ๋ ฌํ ๋ค์ ์ค๋ณต ์ ๊ฑฐ๋ฅผ ์ํํ๋ค.
- ๋ค๋ฅธ ํ ์ด๋ธ๊ณผ ์ค์ ์กฐ์ธ์ ์ํํ์ง ์๊ณ ๋จ์ง ๋ค๋ฅธ ํ ์ด๋ธ์์ ์กฐ๊ฑด์ ์ผ์นํ๋ ๋ ์ฝ๋๊ฐ ์๋์ง ์๋์ง๋ง ์ฒดํฌํ๋ ํํ์ ์ฟผ๋ฆฌ๋ฅผ ์ธ๋ฏธ ์กฐ์ธ์ด๋ผ๊ณ ํ๋ค.
- MySQL 5.7 ๋ฒ์ ์ ์ธ๋ฏธ ์กฐ์ธ ํํ์ ์ฟผ๋ฆฌ๋ฅผ ์ต์ ํํ๋ ๋ถ๋ถ์ด ์๋นํ ์ทจ์ฝํ๋ค๊ณ ํ๋ค.
- ์ธ๋ฏธ์กฐ์ธ์ด ์ผ์ ธ์์ ๋ 57๊ฑด๋ง ์กฐํํ๋ค.
mysql> EXPLAIN SELECT * FROM employees e WHERE e.emp_no IN (SELECT de.emp_no FROM dept_emp de WHERE de.from_date='1995-01-01');
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
| 1 | SIMPLE | <subquery2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | 100.00 | NULL |
| 1 | SIMPLE | e | NULL | eq_ref | PRIMARY | PRIMARY | 4 | <subquery2>.emp_no | 1 | 100.00 | NULL |
| 2 | MATERIALIZED | de | NULL | ref | ix_fromdate,ix_empno_fromdate | ix_fromdate | 3 | const | 57 | 100.00 | Using index |
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)- ๋ฐ๋ฉด ์ธ๋ฏธ์กฐ์ธ์ ๋๊ณ ์คํํ๋ฉด ๋ฌด๋ ค 30๋ง ๊ฑด ์ด์ ์ฝ๊ณ ์ฒ๋ฆฌ๋๋ ๊ฒ์ ์ดํด๋ณผ ์ ์๋ค.
mysql> SET SESSION optimizer_switch='semijoin=off';
Query OK, 0 rows affected (0.00 sec)
mysql> EXPLAIN SELECT * FROM employees e WHERE e.emp_no IN (SELECT de.emp_no FROM dept_emp de WHERE de.from_date='1995-01-01');
+----+-------------+-------+------------+------+-------------------------------+-------------+---------+-------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------------------+-------------+---------+-------+--------+----------+-------------+
| 1 | PRIMARY | e | NULL | ALL | NULL | NULL | NULL | NULL | 300141 | 100.00 | Using where |
| 2 | SUBQUERY | de | NULL | ref | ix_fromdate,ix_empno_fromdate | ix_fromdate | 3 | const | 57 | 100.00 | Using index |
+----+-------------+-------+------------+------+-------------------------------+-------------+---------+-------+--------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)- ์ธ๋ฏธ ์กฐ์ธ ํํ์ ์ฟผ๋ฆฌ์ ์ํฐ ์ธ๋ฏธ ์กฐ์ธ ํํ์ ์ฟผ๋ฆฌ๋ ์ต์ ํ ๋ฐฉ๋ฒ์ด ์กฐ๊ธ ์ฐจ์ด๊ฐ ์๋ค.
- ์ธ๋ฏธ ์กฐ์ธ ํํ๋ 3๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ์ฉํ ์ ์๋ค.
- ์ธ๋ฏธ ์กฐ์ธ ์ต์ ํ
- IN-to-EXISTS ์ต์ ํ
- MATERIALIZATION ์ต์ ํ
- ์ํฐ ์ธ๋ฏธ ์กฐ์ธ ํํ๋ 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.
- IN-to-EXISTS ์ต์ ํ
- MATERIALIZATION ์ต์ ํ
- ์ต๊ทผ ๋์
๋ ์ธ๋ฏธ ์กฐ์ธ ์ต์ ํ๋ ์๋์ ๊ฐ์ ์ต์ ํ ์ ๋ต์ ๊ฐ์ง๊ณ ์๋ค.
- Table Pull-out
- Duplicate Weed-out
- First Match
- Loose Scan
- Materialization
- ์ธ๋ฏธ ์กฐ์ธ์ ์๋ธ์ฟผ๋ฆฌ์ ์ฌ์ฉ๋ ํ ์ด๋ธ์ ์์ฐํฐ ์ฟผ๋ฆฌ๋ก ๋์ง์ด๋ธ ํ ์ฟผ๋ฆฌ๋ฅผ ์กฐ์ธ ์ฟผ๋ฆฌ๋ก ์ฌ์์ฑํ๋ ํํ์ ์ต์ ํ๋ค.
- ์๋ธ์ฟผ๋ฆฌ๊ฐ ์ต์ ํ๊ฐ ๋์ ๋๊ธฐ ์ ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ํ๋ํ๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ด์๋ค.
mysql> EXPLAIN
-> SELECT * FROM employees e
-> WHERE e.emp_no IN (SELECT de.emp_no FROM dept_emp de WHERE de.dept_no='d009');
+----+-------------+-------+------------+--------+---------------------------+---------+---------+---------------------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------------------+---------+---------+---------------------+-------+----------+-------------+
| 1 | SIMPLE | de | NULL | ref | PRIMARY,ix_empno_fromdate | PRIMARY | 16 | const | 46012 | 100.00 | Using index |
| 1 | SIMPLE | e | NULL | eq_ref | PRIMARY | PRIMARY | 4 | employees.de.emp_no | 1 | 100.00 | NULL |
+----+-------------+-------+------------+--------+---------------------------+---------+---------+---------------------+-------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)- ํ ์ด๋ธ ํ์์ ์ต์ ํ๋ ๋ณ๋์ ์คํ ๊ณํ์ Extra ์นผ๋ผ์ "Using table pullout"๊ณผ ๊ฐ์ ๋ฌธ๊ตฌ๊ฐ ์ถ๋ ฅ๋์ง ์๋๋ค. ์ต์ ํ๊ฐ ์ฌ์ฉ๋๋์ง ํ์ธํ๋ ค๋ฉด ํด๋น ํ ์ด๋ธ๋ค์ id ์นผ๋ผ๊ฐ์ด ๊ฐ์์ง ๋ค๋ฅธ์ง ๋น๊ตํด๋ณด๋ ๊ฒ์ด ๊ฐ์ฅ ๊ฐ๋จํ๋ค.
- ์์ ์์์์๋ id ์นผ๋ผ ๊ฐ์ด ๋ชจ๋ 1๋ก ํ์๋๋ ๊ฒ์ผ๋ก ๋ณด์ ํ ์ด๋ธ ํ์์ ์ต์ ํ๊ฐ ์งํ๋ ๊ฒ์ ์ ์ ์๋ค.
mysql> SHOW WARNINGS;
Level: Note
Code: 1003
Message: /* select#1 */
select `employees`.`e`.`emp_no` AS `emp_no`,
`employees`.`e`.`birth_date` AS `birth_date`,
`employees`.`e`.`first_name` AS `first_name`,
`employees`.`e`.`last_name` AS `last_name`,
`employees`.`e`.`gender` AS `gender`,
`employees`.`e`.`hire_date` AS `hire_date`
from `employees`.`dept_emp` `de`
join `employees`.`employees` `e`
where ((`employees`.`e`.`emp_no` = `employees`.`de`.`emp_no`)
and (`employees`.`de`.`dept_no` = 'd009'))
1 row in set (0.00 sec)SHOW WARNINGS๋ช ๋ น์ด๋ฅผ ํตํด ์ฟผ๋ฆฌ๊ฐ ์ด๋ค ์์ผ๋ก ์ฌ์์ฑ๋์๋์ง ํ์ธํ ์ ์๋ค. ํด๋น ์ฟผ๋ฆฌ๋ฅผ ํ์บํด๋ณด๋ฉด IN(subquery) ํํ๋ ์ฌ๋ผ์ง๊ณ JOIN์ผ๋ก ์ฟผ๋ฆฌ๊ฐ ์ฌ์์ฑ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.- ํ
์ด๋ธ ํ์์์ ํน์ฑ์ ์ ๋ฆฌํ๋ฉด ์๋์ ๊ฐ๋ค.
- ์ธ๋ฏธ ์กฐ์ธ ์๋ธ์ฟผ๋ฆฌ์์๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
- ์๋ธ์ฟผ๋ฆฌ ๋ถ๋ถ์ด UNIQUE ์ธ๋ฑ์ค๋ ํ๋ผ์ด๋จธ๋ฆฌ ํค ๋ฃฉ์ ์ผ๋ก ๊ฒฐ๊ณผ๊ฐ 1๊ฑด์ธ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
- ์ ์ฉ๋๋ค ํ๋๋ผ๋ ๊ธฐ๋ณธ ์ฟผ๋ฆฌ์์ ๊ฐ๋ฅํ๋ ์ต์ ํ ๋ฐฉ๋ฒ์ด ๋ถ๊ฐ๋ฅํ ๊ฒ์ ์๋๋ฏ๋ก MySQL์์๋ ๊ฐ๋ฅํ๋ค๋ฉด ํ ์ด๋ธ ํ์์์ ์ต๋ํ ์ ์ฉํ๋ค.
- ํ ์ด๋ธ ํ์์ ์ต์ ํ๋ ์๋ธ์ฟผ๋ฆฌ์ ํ ์ด๋ธ์ ์์ฐํฐ ์ฟผ๋ฆฌ๋ก ๊ฐ์ ธ์์ ์กฐ์ธ์ผ๋ก ํ์ด์ฐ๋ ์ต์ ํ๋ฅผ ์ํํ๋๋ฐ ๋ง์ฝ ์๋ธ์ฟผ๋ฆฌ์ ๋ชจ๋ ํ ์ด๋ธ์ด ์์ฐํฐ ์ฟผ๋ฆฌ๋ก ๋์ง์ด๋ผ ์ ์๋ค๋ฉด ์๋ธ์ฟผ๋ฆฌ ์์ฒด๋ ์์ด์ง๋ค.
- MySQL์์๋ "์ต๋ํ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์กฐ์ธ์ผ๋ก ํ์ด์ ์ฌ์ฉํด๋ผ"๋ผ๋ ํ๋ ๊ฐ์ด๋๊ฐ ๋ง์๋ฐ ํ ์ด๋ธ ํ์์ ์ต์ ํ๋ ์ฌ์ค ์ด ๊ฐ์ด๋๋ฅผ ๊ทธ๋๋ก ์คํํ๋ ๊ฒ์ด๋ค.
- ํผ์คํธ ๋งค์น ์ ๋ต์ IN(subquery) ํํ์ ์ธ๋ฏธ ์กฐ์ธ์ EXIST(subquery) ํํ๋ก ํ๋ํ ๊ฒ๊ณผ ๋น์ทํ ๋ฐฉ๋ฒ์ผ๋ก ์คํ๋๋ค.
- ์คํ ๊ณํ์ ๋ณด๋ฉด Extra ์นผ๋ผ์
FirstMatch(e)๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ํ์๋๋ค.
mysql> EXPLAIN
SELECT * FROM employees e
WHERE e.emp_no IN
(SELECT de.emp_no FROM dept_emp de WHERE de.dept_no='d009');
+----+-------------+-------+------------+--------+---------------------------+---------+---------+---------------------+-------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------------------+---------+---------+---------------------+-------+----------+-------------+
| 1 | SIMPLE | de | NULL | ref | PRIMARY,ix_empno_fromdate | PRIMARY | 16 | const | 46012 | 100.00 | Using index |
| 1 | SIMPLE | e | NULL | eq_ref | PRIMARY | PRIMARY | 4 | employees.de.emp_no | 1 | 100.00 | NULL |
+----+-------------+-------+------------+--------+---------------------------+---------+---------+---------------------+-------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)
- ํผ์คํธ๋งค์น๋ ์๋ธ์ฟผ๋ฆฌ๊ฐ ์๋๋ผ ์กฐ์ธ์ผ๋ก ํ์ด ์คํํ๋ฉด์ ์ผ์นํ๋ ์ฒซ ๋ฒ์งธ ๋ ์ฝ๋๋ง ๊ฒ์ํ๋ ์ต์ ํ๋ฅผ ์คํํ ๊ฒ์ด๋ค.
- ์์์์๋ titles ํ ์ด๋ธ์ ์ผ์นํ๋ ๋ ์ฝ๋ 1๊ฑด๋ง ์ฐพ์ผ๋ฉด ๋์ด์ titles ํ ์ด๋ธ ๊ฒ์์ ํ์ง ์๋๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
- ํผ์คํธ ๋งค์น ์ต์ ํ์ ํน์ฑ์ ์๋์ ๊ฐ๋ค.
- ์๋ธ์ฟผ๋ฆฌ์์ ํ๋์ ๋ ์ฝ๋๋ง ๊ฒ์๋๋ฉด ๋์ด์์ ๊ฒ์์ ๋ฉ์ถ๋ ๋จ์ถ ์คํ ๊ฒฝ๋ก(Short-cut path)์ด๊ธฐ ๋๋ฌธ์ ํผ์คํธ๋งค์น ์ต์ ํ์์ ์๋ธ์ฟผ๋ฆฌ๋ ๊ทธ ์๋ธ์ฟผ๋ฆฌ๊ฐ ์ฐธ์กฐํ๋ ๋ชจ๋ ์์ฐํฐ ํ ์ด๋ธ์ด ๋จผ์ ์กฐํ๋ ์ดํ์ ์คํ๋๋ค.
- ์คํ ๊ณํ์ Extra ์นผ๋ผ์์
FirstMatch(table-N)๋ฌธ๊ตฌ๊ฐ ํ์๋๋ค. - ์๊ด ์๋ธ์ฟผ๋ฆฌ(Correlated subquery)์์๋ ์ฌ์ฉ๋ ์ ์๋ค.
- GROUP BY๋ ์งํฉ ํจ์๊ฐ ์ฌ์ฉ๋ ์๋ธ์ฟผ๋ฆฌ์ ์ต์ ํ์๋ ์ฌ์ฉ๋ ์ ์๋ค.
GROUP BY์ต์ ํ์์ ์ดํด๋ณธ "Using index for group-by"์ ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ(Loose Index Scan)๊ณผ ๋น์ทํ ์ฝ๊ธฐ ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
mysql> EXPLAIN
-> SELECT * FROM departments d
-> WHERE d.dept_no IN(SELECT de.dept_no FROM dept_emp de);
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+--------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+--------------------------------------------+
| 1 | SIMPLE | de | NULL | index | PRIMARY | PRIMARY | 20 | NULL | 331143 | 0.00 | Using index; LooseScan |
| 1 | SIMPLE | d | NULL | ALL | PRIMARY | NULL | NULL | NULL | 9 | 11.11 | Using where; Using join buffer (hash join) |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+--------+----------+--------------------------------------------+
2 rows in set, 1 warning (0.00 sec)- departments ํ ์ด๋ธ์ ๋ ์ฝ๋ ๊ฑด์๋ 9๊ฑด๋ฐ์ ๋์ง ์์ง๋ง dept_emp ํ ์ด๋ธ์ ๋ ์ฝ๋ ๊ฑด์๋ ๋ฌด๋ ค 33๋ง ๊ฑด ๊ฐ๊น์ด ์ ์ฅ๋์ด ์๋ค.
- dept_emp ํ ์ด๋ธ์๋ (dept_no, emp_no) ์กฐํฉ์ ํ๋ผ์ด๋จธ๋ฆฌ ํค ์ธ๋ฑ์ค๊ฐ ๋ง๋ค์ด์ ธ ์๋ค.dept_no๋ง์ผ๋ก ๊ทธ๋ฃจํํด๋ณด๋ฉด ๊ฒฐ๊ตญ 9๊ฑด ๋ฐ์ ์๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
- dept_emp ํ ์ด๋ธ์ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ ๋ฃจ์ค ์ธ๋ฑ์ค ์ค์บ์ผ๋ก ์ ๋ํฌํ dept_no๋ง ์ฝ์ผ๋ฉด ์ค๋ณต๋ ๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ฉด์ ์์ฃผ ํจ์จ์ ์ผ๋ก ์๋ธ์ฟผ๋ฆฌ ๋ถ๋ถ์ ์คํํ ์ ์๋ค.
- ์๋ธ์ฟผ๋ฆฌ์ ์ฌ์ฉ๋ dept_emp ํ ์ด๋ธ์ ํ๋ผ์ด๋จธ๋ฆฌ ํค๋ฅผ dept_no ๋ถ๋ถ์์ ์ ๋ํฌํ๊ฒ ํ ๊ฑด์ฉ๋ง ์ฝ๊ณ ์๋ค๋ ๊ฒ์ ๋ณด์ฌ์ค๋ค.
- ์ธ๋ฏธ ์กฐ์ธ์ ์ฌ์ฉ๋ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ํต์งธ๋ก ๊ตฌ์ฒดํํด์ ์ฟผ๋ฆฌ๋ฅผ ์ต์ ํํ๋ค๋ ์๋ฏธ๋ค.
- ์ฝ๊ฒ ํํํ๋ฉด ๋ด๋ถ ์์ ํ ์ด๋ธ์ ์์ฑํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
mysql> EXPLAIN
-> SELECT *
-> FROM employees e
-> WHERE e.emp_no IN
-> (SELECT de.emp_no FROM dept_emp de
-> WHERE de.from_date='1995-01-01');
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
| 1 | SIMPLE | <subquery2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | 100.00 | NULL |
| 1 | SIMPLE | e | NULL | eq_ref | PRIMARY | PRIMARY | 4 | <subquery2>.emp_no | 1 | 100.00 | NULL |
| 2 | MATERIALIZED | de | NULL | ref | ix_fromdate,ix_empno_fromdate | ix_fromdate | 3 | const | 57 | 100.00 | Using index |
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)- ํด๋น ์ฟผ๋ฆฌ์์ ์ฌ์ฉํ๋ ํ ์ด๋ธ์ 2๊ฐ์ธ๋ฐ ์คํ ๊ณํ์ 3๊ฐ ๋ผ์ธ์ด ์ถ๋ ฅ๋์๋ค. ์คํ ๊ณํ ์ด๋์ ๊ฐ ์์ ํ ์ด๋ธ์ด ์์ฑ๋๋ค๋ ๊ฒ์ ์ง์ํ ์ ์๋ค.
- dept_emp ํ ์ด๋ธ์ ์ฝ๋ ์๋ธ์ฟผ๋ฆฌ๊ฐ ๋จผ์ ์คํ๋์ด ๊ทธ ๊ฒฐ๊ณผ๋ก ์์ ํ ์ด๋ธ()๊ฐ ๋ง๋ค์ด์ก๋ค. ์ต์ข ์ ์ผ๋ก ์๋ธ์ฟผ๋ฆฌ๊ฐ ๊ตฌ์ฒดํ๋ ์์ ํ ์ด๋ธ ()๊ณผ employees ํ ์ด๋ธ์ ์กฐ์ธํด์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
- Materialization๋ ๋ค๋ฅธ ์๋ธ์ฟผ๋ฆฌ ์ต์ ํ์ ๋ค๋ฅด๊ฒ ์๋ธ์ฟผ๋ฆฌ ๋ด์ GROUP BY ์ ์ด ์์ด๋ ์ด ์ต์ ํ ์ ๋ต์ ์ฌ์ฉํ ์ ์๋ค.
mysql> EXPLAIN
-> SELECT *
-> FROM employees e
-> WHERE e.emp_no IN
-> (SELECT de.emp_no FROM dept_emp de
-> WHERE de.from_date='1995-01-01'
-> GROUP BY de.dept_no);
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
| 1 | SIMPLE | <subquery2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | 100.00 | NULL |
| 1 | SIMPLE | e | NULL | eq_ref | PRIMARY | PRIMARY | 4 | <subquery2>.emp_no | 1 | 100.00 | NULL |
| 2 | MATERIALIZED | de | NULL | ref | ix_fromdate,ix_empno_fromdate | ix_fromdate | 3 | const | 57 | 100.00 | Using index |
+----+--------------+-------------+------------+--------+-------------------------------+-------------+---------+--------------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)- Materialization์ ํน์ฑ์ ์๋์ ๊ฐ๋ค.
- IN(subquery)์์ ์๋ธ์ฟผ๋ฆฌ๋ ์๊ด ์๋ธ์ฟผ๋ฆฌ(Correlated subquery)๊ฐ ์๋์ด์ผ ํ๋ค.
- ์๋ธ์ฟผ๋ฆฌ๋ GROUP BY๋ ์งํฉ ํจ์๋ค์ด ์ฌ์ฉ๋ผ๋ ๊ตฌ์ฒดํ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- ๊ตฌ์ฒดํ๊ฐ ์ฌ์ฉ๋ ๊ฒฝ์ฐ์๋ ๋ด๋ถ ์์ ํ ์ด๋ธ์ด ์ฌ์ฉ๋๋ค.







