[MySQL] ๊ฒ์ ์ฟผ๋ฆฌ ์ฑ๋ฅ ๋น๊ต
๊ฐ์
- ner์ ํฌํจํ๋ ๊ธฐ์ฌ๋ค์ ์ถ๋ ฅํ ๋, ํจ์จ์ ์ผ๋ก ๊ฒ์ํ๊ธฐ ์ํ ์ฟผ๋ฆฌ ์ฑ๋ฅ ๋น๊ต
1) JSON_CONTAIN
2) MATCH … AGAINST
3) MATCH … AGAINST + REGEXP
- 100,000๊ฐ์ article๋ก ์งํ
ํ์ธ
EXPLAIN ANALYZE ๋ก ๋ถ์์ ์งํํ๋ค.
1. JSON_CONTAIN
EXPLAIN ANALYZE
SELECT * FROM articles WHERE JSON_CONTAINS(ner, '"์ผ์ฑ"');
-> Filter: json_contains(articles.ner,<cache>('"์ผ์ฑ"'))
(cost=10185.55 rows=98728)
(actual time=0.148..102.554 rows=27555 loops=1)
-> Table scan on articles
(cost=10185.55 rows=98728)
(actual time=0.099..43.564 rows=100000 loops=1)
- Table scan ๋ฐ์: ์ ์ฒด articles ํ ์ด๋ธ์ ์ฒ์๋ถํฐ ๋๊น์ง ํ์ (100,000 rows)
- json_contains()๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ฏ๋ก ๋ชจ๋ ํ์ ์ง์ ๊ฒ์ฌ
- actual time: ์ ์ฒด ์์ ์๊ฐ์ ์ฝ 103ms ์ ๋ ๊ฑธ๋ฆผ
2. MATCH … AGAINST
EXPLAIN ANALYZE
SELECT * FROM articles
WHERE MATCH(ner_text) AGAINST('์ผ์ฑ' IN BOOLEAN MODE);
-> Filter: (match articles.ner_text against ('+์ผ์ฑ' in boolean mode))
(cost=0.35 rows=1)
(actual time=13.105..77.032 rows=49819 loops=1)
-> Full-text index search on articles using idx_ner_text_ngram (ner_text='+์ผ์ฑ')
(cost=0.35 rows=1)
(actual time=13.104..74.931 rows=49819 loops=1)
- FULLTEXT ์ธ๋ฑ์ค ์ฌ์ฉ: idx_ner_text๊ฐ ์ฌ์ฉ๋จ
- ์์ ๋น์ฉ (cost)์ด ๋งค์ฐ ๋ฎ์ (0.35) → ๋งค์ฐ ๊ฐ๋ฒผ์ด ์์ ์ผ๋ก ์ธ์
- actual time: 13.105ms ~ 77.032ms
- 13.105ms : ์ฒซ๋ฒ์ฌ row ๋์จ ์๊ฐ
- 77.032ms : ์ ์ฒด 49819๊ฑด ๋์จ ์๊ฐ
- ์ด๊ฑด ์ธ๋ฑ์ค๋ฅผ ํตํด 50,126๊ฐ์ ๋งค์นญ row๋ฅผ ์ฐพ์
โ JSON_CONTAIN, MATCH … AGAINST ์ ์ถ๋ ฅ ๊ฐ์๊ฐ ๋ค๋ฅด๋ค.
- JSON_CONTAIN: 27555
- MATCH … AGAINST: 49819
- MATCH … AGAINST์ผ๋ก ‘์ผ์ฑ’์ด๋ผ๋ ํค์๋๋ ๊ฒ์ํ์ ๋, ‘์ผ์ฑ’์ ํฌํจํ๋ ner์ ๋ชจ๋ ๊ฒ์ํ๋ค.
- ์: ์ผ์ฑ, ์ผ์ฑ์ ์ ๋ฑ..
- ๋ง์ฝ ‘์ผ์ฑ’์ ํฌํจํ๋ ๋จ์ด๊ฐ ์๋, ์ค์ง ‘์ผ์ฑ’๋ง ๊ฒ์ํ๋ ค๋ฉด ์๋์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
3. MATCH … AGAINST + REGEXP
EXPLAIN ANALYZE
SELECT COUNT(*) FROM articles
WHERE MATCH(ner_text) AGAINST('+์ผ์ฑ' IN BOOLEAN MODE)
AND ner_text REGEXP '\\b์ผ์ฑ\\b';
-> Filter: ((match articles.ner_text against ('+์ผ์ฑ' in boolean mode)) and regexp_like(articles.ner_text,'\\b์ผ์ฑ\\b'))
(cost=0.35 rows=1)
(actual time=9.632..87.606 rows=27555 loops=1)
-> Full-text index search on articles using idx_ner_text_ngram
(ner_text='+์ผ์ฑ') (cost=0.35 rows=1)
(actual time=9.528..73.840 rows=49819 loops=1)
- JSON_CONTAIN์ผ๋ก ๊ฒ์ํ์ ๋์ 27555์ผ๋ก ๋์ผํจ
- REGEXP๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ง ๋ชปํ๋ฏ๋ก ํ์ฒ๋ฆฌ ๋จ๊ณ์์ ์๊ฐ์ด ์ถ๊ฐ๋จ
- ๊ทธ๋๋ Fulltext ์ธ๋ฑ์ค๋ก ๋จผ์ ํํฐ๋ฅผ ๊ฑธ์๊ธฐ ๋๋ฌธ์ ์ ์ฒด ํ ์ด๋ธ ์ค์บ๋ณด๋ค๋ ํจ์ฌ ๋น ๋ฆ
์ ๋ฆฌ
JSON_CONTAINS | MATCH ... AGAINST | |
์ธ๋ฑ์ค ์ฌ์ฉ | ๋ถ๊ฐ (ํ ์ด๋ธ ์ ์ฒด ์ค์บ) | FULLTEXT ์ธ๋ฑ์ค ์ฌ์ฉ |
์๋ (์คํ ์๊ฐ) | ๋น ๋ฅด๊ฒ ์์ํ์ง๋ง ์ค๋ ๊ฑธ๋ฆผ | ์ฝ๊ฐ ๋๋ฆฌ๊ฒ ์์ํ์ง๋ง ๋ ์ต์ ํ๋จ |
์์ธก ๋น์ฉ | ๋์ | ๋งค์ฐ ๋ฎ์ |
ํํฐ๋ง | JSON ๋ด๋ถ๊ฐ ํฌํจ ์ฌ๋ถ ๊ฒ์ฌ | ํ ์คํธ ๊ธฐ๋ฐ ๋จ์ด ๋งค์นญ |
โก๏ธ ๋ฐ์ดํฐ๊ฐ ๋ง์ง ์์ ๋๋ JSON_CONTAINS ๊ฐ ๋ ๋น ๋ฅด์ง๋ง
ํฌ๋กค๋ง์ ์งํํ๋ฉฐ, ๋ฐ์ดํฐ๋ ๊ณ์ ๋์ ๋๋ฉด์ ์์ด ๋ง์์ง ๊ฒ ์ด๊ณ
์ด์ ๋น์ฉ๋ ์ค์ด๊ธฐ ์ํด์๋ MATCH ... AGAINST๊ฐ ๋ ํจ์จ์ ์ด๋ผ๊ณ ํ๋จ๋จ
โก๏ธ ํค์๋ ๊ฒ์ ์, ๊ทธ ํค์๋๋ ํฌํจํ๋ ๊ฒ ๋ชจ๋ ์ถ๋ ฅํ ๊ฒ์ธ์ง / ๊ทธ ํค์๋๋ง ์ถ๋ ฅํ ๊ฒ์ธ์ง๋ ํ๋ก์ ํธ ๋ฐฉํฅ์ ๋ง์ถ์์