25. tháng 3 2025
Chủ đề này thường khiến nhiều người cảm thấy mơ hồ, đặc biệt là sự khác biệt giữa utf8 và utf8mb4. Người ta biết rằng utf8mb4 hỗ trợ tốt hơn cho các ký tự đặc biệt như emoji, nhưng cụ thể về cách cấu hình và lựa chọn quy tắc sắp xếp (collation) thì vẫn còn khá mơ hồ. Dưới đây là hai câu trả lời hữu ích từ StackOverflow mà tôi đã dịch lại và chỉnh sửa một chút.
Đối với những ai vẫn đang gặp phải câu hỏi này vào năm 2020 hoặc sau đó, có một số tùy chọn mới có thể tốt hơn cả hai phương án trước đây. Ví dụ như utf8mb4_0900_ai_ci
.
Tất cả các quy tắc sắp xếp này đều áp dụng cho mã hóa ký tự UTF-8. Sự khác biệt nằm ở cách văn bản được sắp xếp và so sánh.
_unicode_ci
và _general_ci
là hai tập hợp quy tắc khác nhau để sắp xếp và so sánh văn bản theo cách chúng ta mong đợi. Các phiên bản MySQL mới hơn cũng giới thiệu các tập hợp quy tắc mới, chẳng hạn như _0900_ai_ci
, dựa trên chuẩn Unicode 9.0 - không có biến thể tương đương nào của _general_ci
. Những ai đọc bài viết này hiện nay nên cân nhắc sử dụng các quy tắc sắp xếp mới hơn thay vì _unicode_ci
hoặc _general_ci
. Phần mô tả về các quy tắc cũ dưới đây chỉ mang tính chất tham khảo.
MySQL hiện đang dần chuyển đổi khỏi phiên bản UTF-8 cũ và lỗi thời. Hiện tại, bạn cần sử dụng utf8mb4
thay vì utf8
để đảm bảo mình đang dùng phiên bản đã được sửa lỗi. Phiên bản lỗi thời vẫn tồn tại để đảm bảo khả năng tương thích ngược, mặc dù nó đang bị loại bỏ dần.
utf8mb4_unicode_ci
: Dựa trên các quy tắc chính thức của Unicode để sắp xếp và so sánh toàn diện trong phạm vi rộng rãi các ngôn ngữ.utf8mb4_general_ci
: Là một tập hợp quy tắc đơn giản hóa nhằm tối ưu bóng đá trực tiếp tốc độ bằng cách sử dụng các lối tắt. Tuy nhiên, nó không kèo nhà cái tuân theo các quy tắc Unicode và có thể dẫn đến việc sắp xếp hoặc so sánh không mong muốn trong một số trường hợp, ví dụ khi sử dụng các ngôn ngữ hoặc ký tự cụ thể.Trên các máy chủ hiện đại, sự cải thiện về hiệu suất của utf8mb4_general_ci
hầu như không đáng kể. Quy tắc này được phát triển trong thời kỳ máy chủ có hiệu năng CPU thấp hơn rất nhiều so với máy tính ngày nay.
Lợi ích của utf8mb4_unicode_ci
so với utf8mb4_general_ci
:
utf8mb4_unicode_ci
sử dụng thuật toán phức tạp hơn để sắp xếp chính xác trong phạm vi rộng rãi các ngôn ngữ và ký tự đặc biệt. Nó cần xem xét các quy ước riêng biệt của từng ngôn ngữ; không phải ngôn ngữ nào cũng sắp xếp theo thứ tự "bảng chữ cái" mà chúng ta nghĩ tới.utf8mb4_general_ci
trong MySQL không quá lớn, nhưng vẫn có một số điểm khác biệt:
utf8mb4_general_ci
coi chúng là các ký tự đơn lẻ (có lẽ giống "s" và "e").utf8mb4_unicode_ci
xử lý điều này đúng cách.Trong các ngôn ngữ không-Latinh, như ngôn ngữ châu Á hoặc các ngôn ngữ sử dụng bảng chữ cái khác, có thể có nhiều sự khác biệt hơn giữa sắp xếp Unicode và utf8mb4_general_ci
. Độ phù hợp của utf8mb4_general_ci
phụ thuộc rất nhiều vào ngôn ngữ được sử dụng. Đối với một ceo nhà cái số ngôn ngữ, nó có thể không đủ khả năng đáp ứng.
Bạn nên sử dụng gì?
Gần như chắc chắn không có lý do nào để sử dụng utf8mb4_general_ci
nữa, bởi vì hiệu năng CPU hiện đại đã vượt xa mức cần thiết để tạo ra sự khác biệt đáng kể về hiệu suất. Cơ sở dữ liệu của bạn gần như chắc chắn sẽ bị giới hạn bởi các yếu tố khác ngoài vấn đề này.
Trong quá khứ, một số người khuyên nên sử dụng utf8mb4_general_ci
trừ khi việc sắp xếp chính xác quan trọng đến mức đủ để biện minh cho chi phí hiệu suất. Ngày nay, chi phí hiệu suất này hầu như không đáng kể và các nhà phát triển đang nghiêm túc hơn trong việc đối phó với quốc tế hóa.
Có thể nói rằng nếu tốc độ quan trọng hơn độ chính xác đối với bạn, thì bạn thậm chí không cần phải sắp xếp gì cả. Làm cho một thuật toán nhanh hơn khi không cần chính xác là điều rất dễ dàng. Vì vậy, utf8mb4_general_ci
là một sự thỏa hiệp không cần thiết về mặt tốc độ và cũng không phù hợp về mặt độ chính xác.
Ngoài ra, ngay cả khi bạn biết ứng dụng của mình chỉ hỗ trợ tiếng Anh, nó vẫn có thể cần xử lý tên người, vốn thường chứa các ký tự từ các ngôn ngữ khác, nơi mà việc sắp xếp chính xác cũng quan trọng không kém. Sử dụng các quy tắc Unicode cho mọi thứ giúp bạn yên tâm rằng các chuyên gia Unicode đã làm việc rất chăm chỉ để đảm bảo việc sắp xếp hoạt động đúng cách.
Ý nghĩa của các phần:
ci
nghĩa là sắp xếp và so sánh không phân biệt chữ hoa/chữ thường. Điều này phù hợp với dữ liệu văn bản khi chữ hoa/chữ thường không quan trọng. Các kiểu sắp xếp khác bao gồm cs
(phân biệt chữ hoa/chữ thường) cho dữ liệu văn bản khi chữ hoa/chữ thường quan trọng, và bin
cho dữ liệu nhị phân cần khớp từng bit một.unicode
hoặc general
đề cập đến các quy tắc cụ thể về cách sắp xếp và so sánh - đặc biệt là cách văn bản được chuẩn hóa hoặc so sánh. Có nhiều bộ quy tắc khác nhau cho mã hóa ký tự utf8mb4, với unicode
và general
là hai bộ cố gắng hoạt động tốt trong tất cả các ngôn ngữ có thể thay vì một ngôn ngữ cụ thể. Sự khác biệt giữa hai bộ quy tắc này là chủ đề của câu trả lời này. Lưu ý rằng unicode
sử dụng các quy tắc từ Unicode 4.0. Các phiên bản MySQL gần đây thêm các bộ quy tắc unicode_520
(dựa trên Unicode 5.2) và 0900
(dựa trên Unicode 9.0).Cuối cùng, utf8mb4
là mã hóa ký tự được sử dụng bên trong. Trong câu trả lời này, tôi chỉ thảo luận về các mã hóa dựa trên Unicode.