์ ๋ฆฌ์ค-5
by JiwonDev
์ฐ๋ฆฌ๊ฐ ๊ด๊ณํDB๋ฅผ ์ฌ์ฉํ๋ฉด์ ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ์ตํฐ๋ง์ด์ (SQL Optimizer)๊ฐ ์ฟผ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ์คํํ๋์ง์ด๋ค.
๋ฌผ๋ก ์ฐ๋ฆฌ๊ฐ ์์ฑํ SQL๋ฌธ์ ์คํ๊ณํ์ผ๋ก ๋ง๋๋๊ฑด ์ตํฐ๋ง์ด์ ์ ์ญํ ์ด์ง๋ง, ์ฐ๋ฆฌ๋ ์ต์ ์ ์คํ ๊ณํ์ด ์ฌ์ฉ ๋ ์ ์๋๋ก ์ตํฐ๋ง์ด์ ์๊ฒ ํํธ๋ฅผ ์ค ์ ์๋ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด์ผ ํ๋ค.
๐ MySQL ์์ง์์ ์ฟผ๋ฆฌ๊ฐ ์คํ๋๋ ๊ณผ์
- ์ฌ์ฉ์๋ก ๋ถํฐ ์์ฒญ๋ SQL ๋ฌธ์ฅ์ ์๊ฒ ์ชผ๊ฐ ๋ฌธ๋ฒ์ ํ์ธํ๊ณ , Parse ํธ๋ฆฌ๋ก ๋ง๋ ๋ค.
- ๋ง๋ค์ด์ง Parse ํธ๋ฆฌ๋ฅผ ํ์ธํ๋ฉฐ ์ด๋ค ํ
์ด๋ธ๋ถํฐ ์ฝ๊ณ , ์ด๋ค ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ ์ง ์ ํํ๋ค.
+ ๋ถํ์ํ ์กฐ๊ฑด ์ ๊ฑฐ ๋ฐ ์ฐ์ฐ์ ๋จ์ํ ํ๋ค.
+ ์ฌ๋ฌ ํ ์ด๋ธ ์กฐ์ธ์ ํ๋ ๊ฒฝ์ฐ, ํจ์จ์ ์ธ ์์๋ฅผ ๊ฒฐ์ ํ๋ค.
+ ์ธ๋ฑ์ค๋ฅผ ๊ฒฐ์ ํ๋ค. ๊ฐ ํ ์ด๋ธ์์ ์ฌ์ฉ๋ ์กฐ๊ฑด๊ณผ ํต๊ณ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋ค.
+ ๊ฐ์ ธ์จ ๋ ์ฝ๋๋ค์ ์์ ํ ์ด๋ธ์ ๋ฃ์ ๊ฒฝ์ฐ, ๋ค์ ํ๋ฒ ๊ฐ๊ณตํด์ผํ๋์ง ๊ฒฐ์ ํ๋ค. - ๊ฒฐ์ ๋ ์ฝ๊ธฐ์์, ์ ํ๋ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด Storage ์์ง์์ ๊ฐ์ ธ์จ๋ค. (Handler API ์ด์ฉ)
๐ ์ต์ ํ ํ๋ค๋ ๊ฒ์
ํ ํ ์ด๋ธ ์ค์บ์ ์ต์ํํ๊ณ ๋ง๋ค์ด๋ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ๊ฐ์ ํ๋ฒ์ ์ฐพ๋๋ก ๋ง๋ค์ด์ ์ฑ๋ฅ์ ๋์ด ์ฌ๋ฆฐ๋ค๋ ๋ง์ด๋ค.
๋ค๋ง ์์ฅ์์ ์ด์ผ๊ธฐํ์ง๋ง, ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋๊ฒ ๋ฐ๋์ ๋น ๋ฅด๋ค๋ ๋ฒ์ ์๋ค. ์กฐํ๋ฅผ ์ ์ธํ ์ฝ์ /์ญ์ ๋ฑ์ ์ธ๋ฑ์ค์๋ ๊ฐ์ด ๋ฐ์ํด์ค์ผ ํ๊ธฐ์ ๋ ๋๋ ค์ง๋ค.
๋ํ ์กฐํ๋ผ๊ณ ํ๋๋ผ๋ ์๋์ ๊ฐ์ ์ํฉ์์๋ ์ ์ฒด ํ ์ด๋ธ์ ์กฐํํ๋ ๊ฒฝ์ฐ ์ธ๋ฑ์ค๋ฅผ ๊ฑฐ์น๋๊ฒ ๋ ๋๋ฆด ์ ์๋ค.
- ํ ์ด๋ธ์ ๋ ์ฝ๋ ๊ฑด์๊ฐ ๋๋ฌด ์์์ ๊ทธ๋ฅ ํ ํ ์ด๋ธ ์ค์บ์ ํ๋๊ฒ ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ (ํ ์ด๋ธ ํ์ด์ง๊ฐ 1๊ฐ์ธ ๊ฒฝ์ฐ)
- Where ์ ์ด๋ On ์ ์ ์ด์ฉํ ๋งํ๊ฒ ์์ด์ ์ธ๋ฑ์ค๋ฅผ ๋ง๋ค ์ ์๋ ๊ฒฝ์ฐ
- ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ์ด ๊ฐ๋ฅํ๋, ์ผ์น ๋ ์ฝ๋ ์๊ฐ ๋๋ฌด ๋ง์ ๊ฒฝ์ฐ (ํต๊ณ์ ์ผ๋ก ์ ์ฒด ํ ์ด๋ธ์ 20% ์ด์)
๐ Optimizer์ ๋์๋ฐฉ์
์ด์ ์๋ ๋๋ถ๋ถ ๊ท์น ๊ธฐ๋ฐ(Rule-Base)์ ์ตํฐ๋ง์ด์ ์์ง๋ง, ์ต๊ทผ์๋ ๋น์ฉ ๊ธฐ๋ฐ(Cost-Base)์ ์ตํฐ๋ง์ด์ ๊ฐ ์ฌ์ฉ๋๋ค.
์ฆ ์ฟผ๋ฆฌ ๋์์ ๋ ์ฝ๋ ์, ์ ํ๋ ๋ฑ์ ํต๊ณ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์คํ๊ณํ์ ์์ฑํ๋ค.
๊ท์น ๊ธฐ๋ฐ ์ต์ ํ๋ DB์ ๋ด์ฅ๋ ๊ท์น์ ๋ฐ๋ผ ์คํ๊ณํ์ ๋ง๋๋ ๊ฒ์ ์๋ฏธํ๋ค. ๋ค๋ง DB ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์๋น์ค๋ง๋ค ํฌ๊ฒ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ ๋ง ์ค๋๋ DBMS๊ฐ ์๋ ์ด์ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ๋ฐฉ๋ฒ์ด๋ค.
๋ค๋ฅธ ๋ง๋กํ๋ฉด ํต๊ณ ์ ๋ณด๊ฐ ์ ํํ ์๋ก ์ข์ ์คํ ๊ณํ์ ๋ง๋ค ํ๋ฅ ์ด ๋๋ค๋ ์ด์ผ๊ธฐ.
ํน์ ์ฟผ๋ฆฌ์ ์คํ๊ณํ์ EXPLAIN ํค์๋๋ก ํ์ธํ ์ ์๋ค. ์ด๋ ํต๊ณ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์คํ๊ณํ์ ์ ๊ณตํ๋ ๊ฒ์ด๋ค.
mysql> SELECT count(*) FROM t1 JOIN t2 ON (t1.c1 = t2.c2);
+----------+
| count(*) |
+----------+
| 1953125 |
+----------+
mysql> EXPLAIN format=tree --mysql 8.0๋ถํฐ๋ ์ต์
์ ์ฃผ๋ฉด Json์ด๋ Tree ํํ๋ก ๋ณผ ์ ์๋ค.
SELECT * FROM t1 JOIN t2 ON (t1.c1 = t2.c2)\G
*************************** 1. row ***************************
EXPLAIN:
-> Inner hash join (t2.c2 = t1.c1) (cost=976879.74 rows=976563)
-> Table scan on t2 (cost=0.01 rows=3125)
-> Hash
-> Table scan on t1 (cost=314.75 rows=3125)
MySQL ์์ง๋ ํต๊ณ ์ ๋ณด๋ ์ธ๋ฑ์ค๋ฅผ ํตํด ์๋น์ค์ค์๋ ๊ณ์ ์์ง, ์์ ํ๋ค. ์ฐธ๊ณ ๋ก MySQL 8.0๋ถํฐ๋ ์ธ๋ฑ์ค๋ฟ๋ง ์๋๋ผ ์ผ๋ฐ ์นผ๋ผ์๋ ํต๊ณ ์ ๋ณด(Histogram)์ ์์งํ๋ค. ์ค์ ๋ก innodb_stats_sample_pages ์ค์ ๊ฐ์ ์ด์ฉํ๋ฉด ํต๊ณ ์ ๋ณด๋ฅผ ์ํด ๋ถ์ํ ์ธ๋ฑ์ค ํ์ด์ง ๊ฐ์๋ฅผ ์ง์ ํด ์ค ์ ์๋ค.
๋น์ฐํ ๋ถ์ํ ํ์ด์ง ์๊ฐ ๋ง์ผ๋ฉด ์ ๋ณด๊ฐ ๋ ์ ํํ๊ฒ ์ง๋ง, ์์ง ์ค์๋ ํ ์ด๋ธ ์ฝ๊ธฐ/์ฐ๊ธฐ๊ฐ ๋์ง ์์ผ๋ฏ๋ก DB ์ฑ๋ฅ์ ํฐ ์ํฅ์ด ๊ฐ๋ค. ๊ทธ๋์ ์ด ๊ฐ์ ๋ง์๋ 16~24 ํ์ด์ง ์ ๋๋ง ์ฌ์ฉํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ค.
์ฐธ๊ณ ๋ก MySQL 8.0.18์ ์๋ก์ด ๊ธฐ๋ฅ์ผ๋ก EXPLAIN ANALYZE๋ฅผ ์ ๊ณตํ๋ค. ํด๋น ๊ธฐ๋ฅ์ ์ค์ ์ํํ์ ๋( actual ) ์๋น๋๋ ์๊ฐ, ์ฐ์ฐ๋ณ ์ฒ๋ฆฌ ๊ฑด ์, ์์ ์คํ๋น์ฉ๋ฑ์ ํจ๊ป ๋ณด์ฌ์ค๋ค.
mysql> EXPLAIN ANALYZE
SELECT * FROM t1 JOIN t2 ON (t1.c1 = t2.c2)\G
*************************** 1. row ***************************
EXPLAIN:
-> Inner hash join (t2.c2 = t1.c1) (cost=976879.74 rows=976563) (actual time=1.229..74.317 rows=1953125 loops=1)
-> Table scan on t2 (cost=0.01 rows=3125) (actual time=0.006..2.386 rows=3125 loops=1)
-> Hash
-> Table scan on t1 (cost=314.75 rows=3125) (actual time=0.017..0.983 rows=3125 loops=1)
๐ ์คํ๊ณํ ๋ถ์ํ๊ธฐ (Explain)
EXPLAIN <์ฟผ๋ฆฌ> ๋ฅผ ์ ๋ ฅํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์๋์ ๊ฐ์ ์คํ๊ณํ ํ ์ด๋ธ์ ์ ๊ณตํด์ค๋ค.
๋ค๋ง ๊ตณ์ด ์ธ์ธ๋ ค๊ณ ํ๊ธฐ๋ณด๋ค๋, ์์ฃผ ๋ณด๋ค๋ณด๋ฉด ์ด๋ค๊ฒ ์ค์ํ ๊ฐ์ธ์ง ์์ฐ์ค๋ฝ๊ฒ ์์๊ฐ๋๊ฑธ ๊ถ์ฅํ๋ค.
์๋ฅผ ๋ค์ด ์ธ๋ฑ์ค ์ฌ์ฉ๋ฐฉ์์ ๋ํ๋ด๋ type๊ณผ ๋ถ๊ฐ์ ๋ณด๋ฅผ ๋ํ๋ด๋ Extra๋ ์ค์ํ์ง๋ง
ํ๋ณด ์ธ๋ฑ์ค ํค๋ฅผ ๋ณด์ฌ์ฃผ๋ possilbe_keys ๊ฐ์ ๊ฑด ๋ณ ์ธ๋ชจ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ค ์ธ์ฐ๋๊ฑด ์ธ๋ชจ ์๋ ์ง์ด๋ค.
์ฐธ๊ณ ๋ก mysql ์๋ฒ ์ฝ์์ ๊ทธ๋ฅ EXPLAIN์ ์ฐ์ผ๋ฉด ์๋์ ๊ฐ์ด ๋์จ๋ค.
๐ id (select_id) ์นผ๋ผ
SELECT ํญ๋ชฉ์ ๊ตฌ๋ถํ๋ ๋ฒํธ, ์ฌ๋ฌ ํ ์ด๋ธ์ ์กฐํํ๋๋ผ๋ Join์ผ๋ก ์ฐ๊ฒฐ๋์ด ์๋ค๋ฉด ๋ค๋ฅธ ๋์ผํ ID๊ฐ ๋ถ์ฌ๋๋ค.
๐ select_type ์นผ๋ผ
์ฟผ๋ฆฌ๊ฐ ์ด๋ค ํ์
์ธ์ง ๋ํ๋ธ๋ค. ์ฟผ๋ฆฌ ํ์
๋ง ๋ณด๋๋ผ๋ ๋์ถฉ ์ด๋ป๊ฒ ๊ฐ์ ํด์ผ ํ๋์ง ์ ์ ์๋ค.
โ SIMPLE : ์๋ธ์ฟผ๋ฆฌ๋ Union์ ์ฌ์ฉํ์ง ์์ ๋จ์ Select ์ฟผ๋ฆฌ๋ฅผ ์๋ฏธํ๋ค. (Join๋ ๋จ์ ์ฟผ๋ฆฌ๋ก ์ทจ๊ธํ๋ค.)
โ PRIMARY : ์๋ธ์ฟผ๋ฆฌ๋ Union๊ฐ ํฌํจ๋ ์ฟผ๋ฆฌ. ๊ฐ์ฅ ๋ฐ๊นฅ์ชฝ Select๊ฐ PRIMARY๋ก ํ๊ธฐ๋๋ค.
์๊ฐํด๋ณด๋ฉด ๋น์ฐํ๊ฑฐ์ง๋ง, ํ ๊ฐ์ ์ฟผ๋ฆฌ ์คํ ๊ณํ์์ SIMPLE ๊ณผ PRIMARY ๋ ๋ฐ๋์ ํ๋๋ง ์กด์ฌํ๋ค.
โ SUBQUERY : From์ ์ด์ธ์ ์ฌ์ฉ๋ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ์๋ฏธํ๋ค.
โ DERIVED : From์ ์ ์ฌ์ฉ๋ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ์๋ฏธํ๋ค. ๋ฉ๋ชจ๋ฆฌ๋ ๋์คํฌ์ ์์ ํ
์ด๋ธ์ ๋ง๋ ๋ค.
โ UNION : Union์ ์ฌ์ฉํ ๊ฒฝ์ฐ, ๋ ๋ฒ์งธ ์ดํ ์ฟผ๋ฆฌ๋ UNION์ผ๋ก ํ์๋๋ค. ์ฒซ๋ฒ์งธ ์ฟผ๋ฆฌ๋ Union ๊ฒฐ๊ณผ๋ฅผ ๋ํํ๋ DERIVED ํ์
์ ๊ฐ๊ฒ ๋๋ค.
โ DEPENDENT UNION : ๋ด๋ถ ์ฟผ๋ฆฌ๊ฐ ์ธ๋ถ์ ๊ฐ์ ์ฐธ์กฐํ ๋ DEPENDENT ํค์๋๊ฐ ์ถ๊ฐ๋๋ค. Union์ผ๋ก ๊ฒฐํฉ๋ ์ฟผ๋ฆฌ๊ฐ ์ธ๋ถ ์ฟผ๋ฆฌ์ ์ํด ์ํฅ์ ๋ฐ๋๋ค๋ ์๋ฏธ.
โ DEPENDENT SUBQUERY : From ์ ์ด์ธ์ ์ฌ์ฉ๋ ์๋ธ์ฟผ๋ฆฌ๊ฐ ๋ฐ๊นฅ์ชฝ Select ์ฟผ๋ฆฌ(์ธ๋ถ ๊ฐ)์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
โ DEPENDENT DERIVED : ๊ธฐ์กด์๋ From ์ ์ ์๋ธ ์ฟผ๋ฆฌ์ ์ธ๋ถ ์นผ๋ผ์ ์ฌ์ฉํ ์ ์์์ผ๋, MySQL 8.0๋ถํฐ๋ ๊ฐ๋ฅํ๋ค. ๊ทธ๋์ Lateral Join์ผ๋ก From ์ ์ ์๋ธ ์ฟผ๋ฆฌ๊ฐ ์ธ๋ถ ์นผ๋ผ์ ์ฐธ์กฐํ์ ๋ ํด๋น ํ์
์ด ์ฌ์ฉ๋๋ค.
โ UNION RESULT : Union์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ ์์ํ
์ด๋ธ์ ์๋ฏธํ๋ค. ์ฐธ๊ณ ๋ก MySQL8.0 ๋ถํฐ๋ Union ALL์ ์ฌ์ฉํ ๋ ์์ ํ
์ด๋ธ์ ์์ฑํ์ง ์๋๋ค.
โ UNCACHEABLE SUBQUERY : SUBQUERY๋ฅผ ์ฌ์ฉํ๋๋ฐ ํน์ ์กฐ๊ฑด ๋๋ฌธ์ ์บ์๋ฅผ ์ด์ฉํ ์ ์์ ๋ ํ๊ธฐ๋๋ค.
์ด๋ ์ฌ์ฉ์ ๋ณ์๋ UUID, RAND() ๊ฐ์ ๊ฐ์ด ์๋ธ์ฟผ๋ฆฌ์ ๋ค์ด ๊ฐ์์ ์๋ฏธํ๋ค.
โ MATERIALIZED : From ์ ์ด๋ IN (subqurey) ์์ ์๋ธ์ฟผ๋ฆฌ ์ต์ ํ๋ฅผ ์ํด ์ฌ์ฉ๋๋ค.
๋ณดํต ์ด๋ฐ ๊ฒฝ์ฐ ์๋ธ ์ฟผ๋ฆฌ๋ ์ฌ๊ปด๋๊ณ ์ธ๋ถ ์ฟผ๋ฆฌ์ ํ
์ด๋ธ์ ๋จผ์ ์ฝ์ด์ ๋นํจ์จ์ ์ผ๋ก ์คํ๋๋๋ฐ, ์ด๋ฅผ ์ต์ ํ ์์ผ ์๋ธ ์ฟผ๋ฆฌ์ ๋ด์ฉ์ ์์ํ
์ด๋ธ๋ก ๊ตฌ์ฒดํ(Materialzed)ํ ํ ์ธ๋ถ ํ
์ด๋ธ๊ณผ ์กฐ์ธํ๋ ํํ๋ก ์คํ๋๋ค.
๋ค๋ง ๊ฒฐ๊ตญ ์์ํ
์ด๋ธ์ ์ถ๊ฐ๋ก ์ฌ์ฉํ๋ฏ๋ก ๋ณดํต ๊ทน์ ์ธ ์ฑ๋ฅ ํฅ์์ ๊ธฐ๋ํ๊ธฐ ์ด๋ ต๋ค. ๊ทธ๋ฅ ์กฐ๊ธ ๋ ์ข์ ์ ๋
๊ธฐ๋ณธ์ ์ผ๋ก DEPENDENT๋ ์ธ๋ถ ์ฟผ๋ฆฌ์ ์์กด์ฑ์ด ์์ผ๋ฏ๋ก ์ฑ๋ฅ์ด ๋๋ฆฌ๋ค.
๋ํ DERIVED ๊ฐ์ด ์์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ ๊ฒ๋ค์ ๋์คํฌ์ ์์ํ ์ด๋ธ์ด ๋ง๋ค์ด์ง ์ํ์ด ์๋ค. ๊ทธ๋์ Join์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ ํด ์์ํ ์ด๋ธ์ ์ฌ์ฉํ์ง ์๋๋ก ์ ๊ฑฐํ๋ ๊ฒ์ด ์ข๋ค.
๐ table ์นผ๋ผ
๋ณด๋ฉด ์๊ฒ ์ง๋ง ์คํ๊ณํ์ ํ์ธ ํ ๋, SELECT ์ฟผ๋ฆฌ๋ก ๋ถ๋ฅํ๋๊ฒ ์๋๋ผ ํ
์ด๋ธ ๋จ์๋ก ๋ถ๋ฅํด์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
๊ทธ๋์ table ์นผ๋ผ์ ํตํด ์ด๋ค ํ
์ด๋ธ์ ๋ํ ์ ๋ณด์ธ์ง๋ฅผ ๋ํ๋ธ๋ค. ์ฐธ๊ณ ๋ก <>๋ ์์ ํ
์ด๋ธ์ ์๋ฏธํ๋ค.
table ํญ๋ชฉ์ด <DERIVED2>์ธ ๊ฒฝ์ฐ, ID:2๋ฅผ ์ํํ ํ ์งํ๋๋ค๋ ์๋ฏธ.
๐ partitions ์นผ๋ผ
ํํฐ์
๋(partitioning)ํ์ฌ ํ
์ด๋ธ์ ๊ด๋ฆฌํ ๋ ์ด๋ค ํํฐ์
์ ์ฝ์๋์ง ์๋ ค์ฃผ๋ ์ ๋ณด์ด๋ค.
MYSQL 8.0๋ถํฐ๋ ๊ธฐ๋ณธ์ผ๋ก ๋ณด์ด๋๋ฐ, ์ด์ ๋ฒ์ ์์๋ EXPLAIN PARTITION ์ต์
์ ์ค์ผ ๋ณผ ์ ์๋ค.
๐ type ์นผ๋ผ
์คํ๊ณํ ํ๋์ ํต์ฌ์ ์ธ ์นผ๋ผ์ด๋ค. ์คํ ๊ณํ์ด ์ด๋ป๊ฒ ์ธ๋ฑ์ค๋ฅผ ์ฐธ์กฐํ๋์ง๋ฅผ ๋ํ๋ธ๋ค.
์ฐธ๊ณ ๋ก ์์ ์ซ์ (1~12)๋ ํ๊ท ์ ์ธ ์ธ๋ฑ์ค ํจ์จ์ ์ ์ด๋
ผ ๊ฒ. 1. ALL์ด ๊ฐ์ฅ ๋๋ฆฌ๊ณ 12. system ๊ฐ ๊ฐ์ฅ ๋น ๋ฅด๋ค.
1. ALL : ํ ํ
์ด๋ธ ์ค์บ์ด๋ค. ์ธ๋ฑ์ค์ ๊ฐ์ด ์์ด B-TREE ์ ๋๊น์ง ํ์ํ์ฌ ๋์คํฌ ํ์ด์ง๋ฅผ ์ฝ์ด์ ์ฐพ์ ๊ฒฝ์ฐ.
2. index : ๊ฐ์ง๊ณ ์๋ ์ธ๋ฑ์ค๋ฅผ ์ฒ์~๋๊น์ง ๋ค ์ฝ์ ๊ฒฝ์ฐ. ๋๊ฐ์ง ์กฐ๊ฑด์์ ๋ฐ์ํ๋ค
- ์ธ๋ฑ์ค ์ค์บ (range, const, ref)๊ฐ ๋ถ๊ฐ๋ฅ + ์ธ๋ฑ์ค์ ํฌํจ๋ ์นผ๋ผ๋ง์ผ๋ก ์ฒ๋ฆฌ ๊ฐ๋ฅํ ๊ฒฝ์ฐ
- ์ธ๋ฑ์ค ์ค์บ (range, cosnt, ref)๊ฐ ๋ถ๊ฐ๋ฅ + ์ธ๋ฑ์ค๋ง ์ด์ฉํด ์ ๋ ฌ์ด๋ ๊ทธ๋ฃนํ์ด ๊ฐ๋ฅํ ๊ฒฝ์ฐ
3. index_merge : 2๊ฐ ์ด์์ ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ๊ฒฐ๊ณผ๋ฅผ ํฉ์น๋ ๋ฐฉ์. ์ฐ์ ์์๊ฐ range๋ณด๋ค ๋์ง๋ง ํจ์จ์ ์ด์ง ์๋ค.
4. range : ์ธ๋ฑ์ค ๋ ์ธ์ง ์ค์บ, ๊ฐ์ด ์๋๋ผ ์ธ๋ฑ์ค ๋ฒ์๋ก ๊ฒ์ํ๋ ๋ฐฉ๋ฒ์ด๋ค. < > IS NULL BETWEEN LINK IN...
๋ค๋ง ํต์์ ์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ํ๋ค๊ณ ํ๋ฉด range, const, ref๋ฅผ ๋ฌถ์ด์ ์นญํ๋ค.
5. index_subquery : IN ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ๋ ์กฐ๊ฑด์ ๋์ค๋ ๊ฐ์ด ์ ๋ํฌํ์ง ์์ ๊ฒฝ์ฐ(=์ด์ํ ์ฟผ๋ฆฌ) ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํ์ฌ ์ค๋ณต์ ์ ๊ฑฐํ๋ ์ฉ๋๋ก ํด๋น ์ธ๋ฑ์ค๊ฐ ์ฌ์ฉ๋๋ค.
6. unique_subqurey : where ์กฐ๊ฑด์ In (subqurey) ํํ๊ฐ ์์ ๋ ์ฌ์ฉ๋๋ค. ์๋ธ์ฟผ๋ฆฌ์์ ์ ๋ํฌํ ๊ฐ๋ง ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ๋ฅผ ํด๋น ์ธ๋ฑ์ค๊ฐ ์ฌ์ฉ๋๋ค.
7. ref_or_null : ref + IS NULL ์ ํํ. ref๋ณด๋ค ๋๋ฆฌ๋ค. ๋ณดํต ์ค์ ์๋น์ค์ ์คํ ๊ณํ์์๋ ๋ณผ์ผ์ด ๊ฑฐ์ ์๋ค.
8. fulltext : ์ ๋ฌธ(full) ๊ฒ์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํด์ ๋ ์ฝ๋์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ. ์ ๋ฌธ ๊ฒ์ํ ์นผ๋ผ์ ์ธ๋ฑ์ค๊ฐ ์์ด์ผํ๋ค.
MATCH ... AGAINST .. ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋๋ฐ ๋น์ฅ ์ฌ์ฉํ ์ผ์ ์์ผ๋ ์ผ๋จ ๋์ด๊ฐ์.
9. ref : JOIN ์์์ ์๊ด์์ด ์ฌ์ฉ๋๋ค. PK๋ ์ ๋ํฌ ์ธ๋ฑ์ค๋ฑ ์ ์ฝ๋ ์๊ด์์ด ์ฌ์ฉ๋๋ฉฐ ๋๋ฑ ์กฐ๊ฑด(equal)์ด ์ฌ์ฉ๋ ๋ ์ด์ฉํ๋ ์ธ๋ฑ์ค ์ ๊ทผ ๋ฐฉ์์ด๋ค. ์๋นํ ๋น ๋ฅด๋ค.
10. eq_ref : ์ฌ๋ฌ ํ
์ด๋ธ์ด JOIN ๋๋ ์ฟผ๋ฆฌ์๋ง ๋ฐ์ํ๋ค. ์กฐ์ธ์์ ์ฒ์ ์ฝ์ ํ
์ด๋ธ์ ์นผ๋ผ ๊ฐ์ด ๋์ค์ ๋ ์ฝ๋ ํ
์ด๋ธ์ PK, ์ ๋ํฌ ์ธ๋ฑ์ค ์นผ๋ผ์ ๋๋ฑ ์กฐ๊ฑด์์ ์ฌ์ฉ๋ ๋ ์ฌ์ฉ๋๋ ๋ฐฉ๋ฒ์ด๋ค.
์ฆ ref์์ ๋ฐ๋์ 1๊ฑด๋ง ์กด์ฌํ๋ค๋ ๋ณด์ฅ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ๋๋ ํ์
์ด๋ผ๊ณ ์ดํดํ๋ฉด ๋๋ค. ๋ ๋น ๋ฅด๋ค.
11. const : ์ ๋ํฌ ์ธ๋ฑ์ค ์ค์บ, ์ฟผ๋ฆฌ์ PK/์ ๋ํฌ ์นผ๋ผ์ ์ด์ฉํ๋ where ์กฐ๊ฑด์ด ์๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ 1๊ฑด์ผ ๋ ์ฌ์ฉํ๋ค. ๋จ ์คํ ์ ๊ฒฐ๊ณผ๊ฐ 1๊ฐ๋ฐ์ ์์์ DBMS๊ฐ ์์ธกํ ์ ์๋ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ๋๋ค.
12. system: ํ
์ด๋ธ์ ๋ ์ฝ๋๊ฐ 1๊ฑด ์ดํ์ผ ๋ ์ ๊ทผ๋ฐฉ๋ฒ. MySQL์ InnoDB์์๋ ์ฌ์ฉํ์ง ์๋ ๋ฐฉ๋ฒ์ด๋ค.
๐ possible_keys ์นผ๋ผ
์ตํฐ๋ง์ด์ ๊ฐ ์ฌ์ฉ์ ๊ณ ๋ คํ ํ๋ณด ์ธ๋ฑ์ค ๋ชฉ๋ก์ด๋ค.
๐ key ์นผ๋ผ
์ค์ ์ฌ์ฉํ ์ธ๋ฑ์ค์ด๋ค. (possible_keys์ค ํ๋) ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ์์๋ค๋ฉด null์ ๋ฐํํ๋ค.
๐ key_len ์นผ๋ผ
์ธ๋ฑ์ค๋ฅผ ๋ค์ค ์นผ๋ผ์ผ๋ก ์ฌ์ฉํ์ ๋, ์ธ๋ฑ์ค ์ค ๋ช ๋ฐ์ดํธ๊น์ง ์ฌ์ฉํ๋์ง ์๋ ค์ค๋ค.
์๋ฅผ ๋ค์ด SELECT * FROM table WHERE no=2; ์์ key_len์ ๊ฐ์ด 4๊ฐ ๋์๋ค๋ฉด ์ด๋ Integer(=4๋ฐ์ดํธ)ํ ๊ฐ๋ง ์ฌ์ฉํ์์ ์ ์ ์๋ค. ์ฆ ๋ค์ค์นผ๋ผ ์ธ๋ฑ์ค๋ฅผ ์กฐํํ ๋ ๋ชจ๋ ๊ฐ์ ์ฌ์ฉํ๋์ง ์ฌ๋ถ๋ฅผ ํ๋จํ ์ ์๋ค.
๐ ref ์นผ๋ผ (type - ref์ผ ๋)
type์์ ref (๋๋ฑ์กฐ๊ฑด์ด ์ฌ์ฉ๋ ๋ ์ธ๋ฑ์ค ์ ๊ทผ๋ฐฉ๋ฒ, 1๊ฐ์์ ๋ณด์ฅ์ ๋ชปํจ)๊ฐ ์ฌ์ฉ๋ฌ๋ค๋ฉด ref ์นผ๋ผ์ด ์ถ๊ฐ๋ก ์ ๊ณต๋๋ค.
์ด๋ ์ด๋ค ์นผ๋ผ์ด ์กฐ๊ฑด์ ์ฌ์ฉ๋์๋์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ฉฐ, ๋ง์ฝ func๋ผ๊ณ ํ์๋๋ค๋ฉด ๊ฐ๊ณต๋ ์นผ๋ผ์ด ์ฌ์ฉ๋ฌ์์ ์๋ฏธํ๋ค.
๐ row ์นผ๋ผ
์ตํฐ๋ง์ด์ ๊ฐ ์์ธกํด๋ณธ ์ฌ์ฉํ ๋ ์ฝ๋ ์์ด๋ค. ํต๊ณ์ ์ํ ๊ฐ์ด๋ผ์ ์ค์ ๋ ์ฝ๋ ์์ ์ผ์นํ์ง๋ ์๋๋ค.
๐ Extra ์นผ๋ผ
MySQL์ด SQL๋ฌธ์ ์ด๋ป๊ฒ ์คํ๊ณํ์ผ๋ก ๋ง๋ค์๋์ง์ ๋ํ ๋ถ๊ฐ ์ ๋ณด์ด๋ค. ์ฌ๋ฌ ๊ฐ๊ฐ ๋์์ ๋์ฌ ์ ์๋ค.
์ธ์ฐ๊ธฐ์๋ Extra ์ข
๋ฅ๊ฐ ๋๋ฌด ๋ง๋ค. ๋ค๋ง ๋ฌธ๊ตฌ๋ก ๋์ค๋ฏ๋ก ๋์ถฉ ์ฝ์ด๋ณด๋ฉด ๋ฌด์จ ์๋ฏธ์ธ์ง ์ถ์ธก ๊ฐ๋ฅํ๋ค.
- const row not found : const ๋ฐฉ์์ผ๋ก ์ฝ์์ง๋ง ๋ ์ฝ๋๊ฐ 0๊ฐ์
๋๋ค.
- distinct : ํ์ํ ๊ฒ๋ง ์กฐ์ธํ๊ณ ์ค๋ณต๋ ๊ฐ์ ์ ๊ฑฐํ์์ต๋๋ค.
- Full scan on Null key : where ์กฐ๊ฑด์ null์ด ๋ค์ด๊ฐ ์ ์๋ ๊ฐ์ ์ฌ์ฉํ์. null ๋จ๋ฉด ํ ์ค์บ์ผ๋ก ๋ฐ๊พธ๊ฒ ์ต๋๋ค.
- Impossible Having : having์กฐ๊ฑด์ ๋ง์กฑ๋๋ ๋ ์ฝ๋๊ฐ ์์ต๋๋ค. ์๋ชป๋ ์ฟผ๋ฆฌ์
๋๋ค.
- Impossible Where : where ์กฐ๊ฑด์ด ํญ์ False์
๋๋ค. ์๋ชป๋ ์ฟผ๋ฆฌ์
๋๋ค.
- Impossible Where noticed after reading const table : ์ฟผ๋ฆฌ ์คํํด๋ณด๋ Where์ด ํญ์ false์
๋๋ค. ์๋ชป๋ ์ฟผ๋ฆฌ.
- No matching min/max row : Where ์กฐ๊ฑด์ ์ผ์นํ๋ ๋ ์ฝ๋๊ฐ ์์ด์ min() max()๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
- No matching row in const table : const ๋ฐฉ์์ผ๋ก ์ ๊ทผํ ๋ ์ผ์นํ๋ ๋ ์ฝ๋๊ฐ ์์ต๋๋ค.
- No tables used : from ์ ์ด ์์ต๋๋ค. (from dual์ผ๋ก ๋๋ฏธ ํ
์ด๋ธ ์กฐํํ ๊ฒฝ์ฐ)
- Not exist : ๋ ํ
์ด๋ธ A, B์์ ์์ ํ์ชฝ์๋ง ๊ฐ์ด ์กด์ฌํฉ๋๋ค. โก ์ด ๊ฒฝ์ฐ 2๊ฐ์ง ์กฐ์ธ์ ์ฌ์ฉํ๋ค.
1. Anti-Join : NOT IN (subqurey) ๋๋ NOT EXISTS ์ผ๋ก ํ์ฌ ํ
์ด๋ธ์ ์๋ ๊ฐ์ ์กฐ์ธํ๋ ๋ฐฉ๋ฒ
2. Left Outer Join : ๋ ์ฝ๋๊ฐ ๋ง์ ๋ ์ํฐ ์กฐ์ธ ๋์ ๋ ์ฝ๋ ์กด์ฌ ์ฌ๋ถ๋ง ํ๋จ(NOT EXISTS)ํ๋๋ก ์ต์ ํ.
SELECT *
FROM dept_emp de LEFT JOIN departments d ON de.dept_no = d.dept_no
WHERE d.dept_no IS NULL; --NOT EXISTS
- Range checked for each record (index map : N) : ๋ ํ
์ด๋ธ ์กฐ์ธ์, Where ์กฐ๊ฑด์ ๋ณ์๊ฐ ์ฌ๋ฌ๊ฐ ์ฌ์ฉ๋์ด ๊ณ์ ๊ฐ์ด ๋ฐ๋๋ ๊ฒฝ์ฐ. ๋ ์ฝ๋๋ง๋ค [์ธ๋ฑ์ค ์ฌ์ฉ/ ํ์ค์บ]์ด ๋ฌ๋ผ์ง๋ ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํ๋ค๋ ์๋ฏธ.
- Scanned N databases : ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฉํ์ ๋ณด๋ฅผ ์กฐํํ ๊ฒฝ์ฐ
- Select tables optimized away : MIN() MAX() ๋ฑ์ด ์ธ๋ฑ์ค๋ฅผ ์ด์ฉํด ๋จ 1๊ฑด์ ์กฐํ๋ก ์ฐพ์ ์ ์๊ฒ ์ ์ต์ ํ ๋ ๊ฒฝ์ฐ.
- unique row not found : ๋๊ฐ์ ํ
์ด๋ธ์ PK๋ ์ ๋ํฌ ์นผ๋ผ์ผ๋ก ์์ฐํฐ ์กฐ์ธํ ๋, ์ผ์นํ๋ ๋ ์ฝ๋๊ฐ ์์ ์๋ ๊ฒฝ์ฐ
- Using filesort : ORDER BY๋ฅผ ์ธ๋ฑ์ค๋ก ์ฒ๋ฆฌํ์ง ๋ชปํ ๊ฒฝ์ฐ. MySQL์์ ๊ฐ์ Sort buffer๋ก ๋ณต์ฌํด์ ์ ๋ ฌํ์์ ๊ฒฝ๊ณ
ํํ ๋ณผ ์ ์๋ ๋นํจ์จ์ ์ธ ์ผ์ด์ค์ด๋ค. ์ ๋ ฌ์ ์ฌ์ฉํด์ SQL์ ํ๋ํ์.
- Using index : ์ปค๋ฒ๋ง ์ธ๋ฑ์ค, ๋ฐ์ดํฐ ํ์ผ์ ์์ ์์ฝ๊ณ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ๊ฒฝ์ฐ. (* type ์นผ๋ผ์ index๋ ํ์ค์บ์ ์๋ฏธํจ.)
- Using index for group-by : ๋ฃจ์ฆ ์ธ๋ฑ์ค ์ค์บ. Group By ์ฒ๋ฆฌ๋ฅผ ์ํด ์ ๋ ฌ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ.
- Using Join Buffer : ์กฐ์ธ ๋ฒํผ๋ฅผ ์ฌ์ฉํ์์ ์๋ฏธํ๋ค. ์ผ๋ฐ์ ์ผ๋ก ์กฐ์ธ์ ์ฌ์ฉ๋๋ ์นผ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ค.
๋ ํ
์ด๋ธ์ Join ํ์ ๋, ๋จผ์ ์ฝ์ ํ
์ด๋ธ์ ๋๋ผ์ด๋น(Driving), ๋์ค์ ์ฝ์ ํ
์ด๋ธ์ ๋๋ฆฌ๋ธ(Driven)์ด๋ผ ํ๋ค.
๋์ค์ ์ฝ์ ๋๋ฆฌ๋ธ ํ
์ด๋ธ์ Join ์นผ๋ผ ์ธ๋ฑ์ค๊ฐ ์๋ค๋ฉด ์กฐ์ธ ๋ฒํผ๋ฅผ ๋ง๋ค์ด์ ์ ๊น ์ ์ฅํด๋๋ค. ์ด ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
+์ ํจํ ์กฐ์ธ์กฐ๊ฑด์ ์ ์ง ์์์, ๋ชจ๋ ๊ฒฝ์ฐ์ ์ ๋ ์ฝ๋๊ฐ ๋ง๋ค์ด์ง๋ Cartesian Product ์กฐ์ธ๋ ์กฐ์ธ๋ฒํผ๋ฅผ ์ฌ์ฉํ๋ค.
- Using union, Using intersect, Using sort_union, : 2๊ฐ ์ด์์ ๋ค์ค์ปฌ๋ผ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ๋ (type=index_merge) ๊ฒฐ๊ณผ๊ฐ ์ด๋ป๊ฒ ํฉ์ณ์ก๋์ง๋ฅผ ์๋ ค์ค๋ค. ์กฐ๊ฑด์ด OR์ด๋ผ ํฉ์งํฉ์ผ๋ก ์ถ์ถํ๋์ง, AND๋ผ ๊ต์งํฉ์ผ๋ก ์ถ์ถํ๋์ง ์๋ ค์ค๋ค.
๋จ sort_union์ ํฉ์งํฉ ์ถ์ถ๊ณผ ๊ฐ์ง๋ง ์ฐ๊ฒฐ๋ ๋ ์ฝ๋๊ฐ ๋๋์ range๋ฅผ ํ์ํ๋ ์กฐ๊ฑด์ด๋ผ ํ๋ฒ์ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒฝ์ฐ PK๋ง ๋จผ์ ์ฝ์ด์ ์ ๋ ฌ โก ๋ณํฉํ์ฌ ๋ฐํํ์์ ์๋ฏธํ๋ค.
- Using temporary : ์์ํ
์ด๋ธ์ ์ฌ์ฉ๋์์์ ์๋ฏธํ๋ค. ๋ค๋ง ์ฌ์ฉํ๋๋ฐ Using temporary๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์ข
์ข
์๋ค.
์ฐธ๊ณ ๋ก ์์ํ
์ด๋ธ์ด ์์ฑ๋๋ ๊ฒฝ์ฐ๋ ๋์ถฉ ์๋์ ๊ฐ๋ค.
โ FROM ์ ์ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์ฐ๋ฉด ๋ฌด์กฐ๊ฑด ์์ํ
์ด๋ธ(Derived table)์ด ์์ฑ๋๋ค.
โ "COUNT(DISTINCT column1)" ๊ฐ์ ์ฟผ๋ฆฌ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ์ ์์ ํ
์ด๋ธ์ด ๋ง๋ค์ด์ง๋ค.
โ UNION, UNION ALL์ด ์ฌ์ฉ๋ ์ฟผ๋ฆฌ๋ ํญ์ ์์ ํ
์ด๋ธ์ ์ฌ์ฉํ๋ค.
โ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ ์ ๋ ฌ ์์
๋ ์์ ํ
์ด๋ธ์ ์ฌ์ฉํ๋ค.
- Using where : MySQL์์ง์ด ์ฟผ๋ฆฌ๋ฅผ ๊ฐ๊ณต/ํํฐ๋ง ํ ๊ฒฝ์ฐ ๋ํ๋๋ค. ์ฒดํฌ ์กฐ๊ฑด์ MySQL ์์ง์์ ์ฒ๋ฆฌํ๋ค.
๋ฒ์ ์กฐ๊ฑด์ ์คํ ๋ฆฌ์ง ์์ง์์ ์ฒ๋ฆฌ ํ ๋ ์ฝ๋๋ฅผ ๋ฆฌํดํ์ง๋ง, ์ฒดํฌ ์กฐ๊ฑด์ Using where์ด ๊ฐ๋ฅํ๋ค.
SELECT * FROM table WHERE man_no BETWEEN 0 AND 10 AND gender = 'M';
-- ๋ฒ์์กฐ๊ฑด BETWEEN์ ์คํ ๋ฆฌ์ง ์์ง์ ์ํด 10๊ฐ์ ๋ ์ฝ๋๊ฐ ๋ฆฌํด๋๊ณ
-- ๊ฐ์ ธ์จ 10๊ฐ์ค์ ์ฒดํฌ ์กฐ๊ฑด gender='M' ์ธ ๊ฒ์ MySQL์์ง์ ์ํด ํํฐ๋ง๋์ด Using Where ๋ฑ์ฅ
- zero limit
๊ฐํน ์ฟผ๋ฆฌ ๋ฐ์ดํฐ๋ ํ์์๊ณ , ๋ฉํ๋ฐ์ดํฐ๋ง ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์ด ๋ Limit 0๋ฑ์ ์ฌ์ฉํ๋ฉด ์คํ๊ณํ์ zero limit์ด ๋์ค๋๋ฐ, ์ด๋ ์์ ๋ฐ์ดํฐ ์กฐํ๋ฅผ ํ์ง ์์์์ ์๋ฏธํ๋ค.
๐ Filtered ์นผ๋ผ (Extra - Using Where ์ ๋)
MySQL8.0์์๋ ๊ธฐ๋ณธ์ผ๋ก ๋์ค๊ณ , ์ด์ ๋ฒ์ ์์๋ EXPLAIN EXTENDED๋ฅผ ์ฌ์ฉํด์ผ ๋์จ๋ค.
Extra ์นผ๋ผ์์ Using where์ด ๋ฌ ๊ฒฝ์ฐ (= MySQL์ด ๋ณ๋์ ํํฐ๋ง, ๊ฐ๊ณต์ ํ ๊ฒฝ์ฐ)
์ผ๋ง๋ ๋ง์ ๋ ์ฝ๋๊ฐ ํํฐ๋ง ๋์๋์ง ๋ํ๋ธ๋ค. ๋ค๋ง ์ด๋ ์ค์ ๊ฒฐ๊ณผ๊ฐ ์๋๋ผ, ํต๊ณ์ ๊ธฐ๋ฐํ ์์ธก ๊ฐ์ด๋ค.
'๐ฑBackend > DB(MySQL,PostgreSQL)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
PostgreSQL ์ vaccum์ ๋ํด ์์๋ณด์. (2) | 2024.05.26 |
---|---|
์ ๋ฆฌ์ค-6 (0) | 2021.10.27 |
์ ๋ฆฌ์ค - 4 (0) | 2021.10.20 |
์ ๋ฆฌ์ค - 3 (0) | 2021.10.20 |
์ ๋ฆฌ์ค -2 (0) | 2021.10.20 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev