search_test
테이블에는 약 1천만 건의 레코드가 존재하며 value 컬럼은 LONGTEXT이고 INDEX가 걸려 있는 테이블이다.
LIKE ‘keyword%’
컬럼이 INDEX되었을 때 컬럼의 prefix로 검색하는 것은 INDEX 스캔을 할 수 있기 때문에 속도가 매우 빠르다.
SELECT SQL_NO_CACHE COUNT(*)
FROM search_test
WHERE value LIKE 'robert%';
+----------+
| COUNT(*) |
+----------+
| 3441 |
+----------+
1 row in set (0.00 sec)
INDEX 스캔이기 때문에 속도는 빠르지만, prefix search는 전문 검색이라고 할 수 없다.
LIKE ‘%keyword%’
infix search를 사용하면 전문 검색을 할 수 있지만 역시 INDEX를 활용하지 못하기 때문에 속도가 느리다.
SELECT SQL_NO_CACHE COUNT(*)
FROM search_test
WHERE value LIKE '%robert%';
+----------+
| COUNT(*) |
+----------+
| 5034 |
+----------+
1 row in set (9.73 sec)
REGEXP()
정규 표현식을 이용하여 전문 검색을 할 수도 있다. 그러나 역시 Full scan을 해야 하므로 속도가 느리다.
SELECT SQL_NO_CACHE COUNT(*)
FROM search_test
WHERE value REGEXP ('robert');
+----------+
| COUNT(*) |
+----------+
| 5034 |
+----------+
1 row in set (9.16 sec)
MATCH AGAINST
MySQL에서 지원하는 전문 검색 기능을 활용한 결과이다. 0.02초 밖에 걸리지 않았다.
SELECT SQL_NO_CACHE COUNT(*)
FROM search_test
WHERE MATCH(value) AGAINST('*robert*' IN BOOLEAN MODE)
+----------+
| COUNT(*) |
+----------+
| 3505 |
+----------+
1 row in set (0.02 sec)
검색 결과 개수가 3,505개로서 앞선 결과와 개수가 다르다는 것에 주의하기 바란다. MATCH AGAINST를 사용하는 경우 MySQL은 문자열을 미리 색인 해두어야 하는데, 이 색인 때문에 LIKE의 결과와 달라질 수 있다. LIKE나 REGEXP를 활용하는 방법은 ‘robert’ 바로 앞 뒤에 어떠한 문자가 나오던지 검색이 된다. 하지만, ‘robert’ 앞 뒤에는 공백 문자나 기호가 있어야만 ‘robert’라는 단어가 색인이 될 것이다. MATCH AGAINST 사용 시에는 색인된 개별 단어 사이에서 LIKE ‘keyword%’처럼 prefix search를 한다고 생각하면 쉽다.
MATCH AGAINT는 MySQL 5.5 이하에서는 MyISAM에서만 사용할 수 있으며, MySQL 5.6부터는 InnoDB에서도 사용할 수 있다.
기타 전문 검색 방법
최근엔 검색 엔진과 MySQL을 연동하기도 쉬워졌다. MySQL과 연동할 수 있는 검색 엔진으로 ElasticSearch, Sphinx, Solr과 같은 것들이 있다. 필자가 직접 사용해 보지는 않았지만, Sphinx와 MySQL을 연동하는 튜토리얼을 읽어보니 매우 좋은 기능 같았다. 한글도 무리 없이 검색할 수 있었고, 검색 속도 또한 빨랐다.
“MySQL” 카테고리의 추천 글
- MySQL IN subquery 성능. IN sub query는 가급적 사용을 피하자
- MySQL의 IN() v.s. EXISTS v.s. INNER JOIN 성능 비교
- MySQL INNER JOIN v.s EXISTS 성능 비교
- JOIN에서 중복된 레코드 제거하기
- MySQL 중복 레코드 관리 방법 - INSERT IGNORE, REPLACE INTO, ON DUPLICATE UPDATE
- MySQL GROUP BY 성능 최적화를 위한 INDEX 설계
- MySQL Query Cache를 빠르게 비우기
- MySQL Plugin에 대한 간단한 소개
- MySQL InnoDB Index Statistics
- MySQL Foreign key 사용 시 주의 사항 (Can’t create table (errno: 150))