Nếu bạn đã từng thử full-text search tiếng Việt trong MySQL thì chắc hẳn biết cảm giác — kết quả thiếu lung tung, từ quan trọng thì không tìm được. Mình cũng gặp vấn đề này khi làm project và phải mò một hồi mới hiểu nguyên nhân. Hóa ra config mặc định của MySQL không phù hợp với tiếng Việt.
Vấn đề ở config mặc định
MySQL mặc định có mấy cái gây khó cho tiếng Việt:
- Không đánh index cho từ ngắn hơn 3 ký tự. Tiếng Việt thì đầy từ 1-2 ký tự có nghĩa.
- Danh sách stopword mặc định lọc bỏ các từ “phổ biến” — nhưng nó thiết kế cho tiếng Anh, nên có thể loại luôn các từ tiếng Việt quan trọng.
- Không hỗ trợ tách từ tiếng Việt. Tiếng Việt đa âm tiết, nhiều dấu, tokenizer mặc định không xử lý tốt.
Cách sửa
Thêm mấy dòng này vào file my.cnf:
ft_min_word_len=1
ft_stopword_file=""
innodb_ft_enable_stopword="OFF"
innodb_ft_min_token_size=1
Giải thích:
ft_min_word_len=1— đánh index từ 1 ký tự trở lên.ft_stopword_file=""— tắt luôn danh sách stopword mặc định.innodb_ft_enable_stopword="OFF"— tắt stopword cho InnoDB.innodb_ft_min_token_size=1— cho InnoDB index luôn các từ ngắn.
Sau khi đổi config
Cần rebuild lại full-text index:
ALTER TABLE ten_bang DROP INDEX ten_index;
ALTER TABLE ten_bang ADD FULLTEXT(ten_cot);
Rồi query bình thường:
SELECT * FROM ten_bang WHERE MATCH(ten_cot) AGAINST('tìm kiếm tiếng việt' IN NATURAL LANGUAGE MODE);
Lưu ý
- Giảm min word length xuống 1 sẽ làm tăng kích thước index và có thể ảnh hưởng hiệu năng với bảng lớn. Nhưng đáng đánh đổi cho tiếng Việt.
- MySQL vẫn không tách từ tiếng Việt tự động được. Từ ghép không có dấu cách thì kết quả vẫn chưa hoàn hảo. Nếu cần chính xác hơn thì nên dùng thư viện tách từ ở tầng ứng dụng.
- Với hệ thống production search traffic lớn, nên cân nhắc Elasticsearch hoặc Meilisearch — hỗ trợ tiếng Việt tốt hơn nhiều.