Đối với những người vẫn đến câu hỏi này vào năm 2020 hoặc muộn hơn, có các tùy chọn mới hơn có thể tốt hơn cả hai trong số này. Ví dụ:utf8mb4_0900_ai_ci
.
Tất cả các đối chiếu này dành cho mã hóa ký tự UTF-8. Sự khác biệt là cách văn bản được sắp xếp và so sánh.
_unicode_ci
và _general_ci
là hai bộ 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 bộ quy tắc mới, chẳng hạn như _0900_ai_ci
cho các quy tắc tương đương dựa trên Unicode 9.0 - và không có _general_ci
tương đương khác nhau. Những người đang đọc nội dung này bây giờ có lẽ nên sử dụng một trong những ảnh ghép mới hơn này thay vì _unicode_ci
hoặc _general_ci
. Mô tả của những ảnh ghép cũ hơn dưới đây chỉ được cung cấp cho mục đích quan tâm.
MySQL hiện đang chuyển đổi từ cách triển khai UTF-8 cũ hơn, thiếu sót. Hiện tại, bạn cần sử dụng utf8mb4
thay vì utf8
đối với phần mã hóa ký tự, để đảm bảo bạn đang nhận được phiên bản cố định. Phiên bản thiếu sót vẫn còn để tương thích ngược, mặc dù nó không được dùng nữa.
Sự khác biệt chính
-
utf8mb4_unicode_ci
dựa trên các quy tắc Unicode chính thức để phân loại và so sánh chung, phân loại chính xác trong nhiều ngôn ngữ. -
utf8mb4_general_ci
là một tập hợp các quy tắc sắp xếp được đơn giản hóa nhằm mục đích làm tốt nhất có thể trong khi thực hiện nhiều đường tắt được thiết kế để cải thiện tốc độ. Nó không tuân theo các quy tắc Unicode và sẽ 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, chẳng hạn như 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, việc tăng hiệu suất này sẽ là tất cả nhưng không đáng kể. Nó được phát minh ra trong thời điểm mà các máy chủ chỉ có một phần rất nhỏ hiệu suất CPU của các máy tính ngày nay.
Lợi ích của utf8mb4_unicode_ci
qua utf8mb4_general_ci
utf8mb4_unicode_ci
, sử dụng các quy tắc Unicode để sắp xếp và so sánh, sử dụng một thuật toán khá phức tạp để sắp xếp chính xác trong nhiều ngôn ngữ và khi sử dụng nhiều ký tự đặc biệt. Các quy tắc này cần phải tính đến các quy ước dành riêng cho ngôn ngữ; không phải ai cũng sắp xếp các ký tự của họ theo thứ mà chúng tôi gọi là 'thứ tự bảng chữ cái'.
Đối với các ngôn ngữ Latinh (tức là "Châu Âu"), không có nhiều sự khác biệt giữa cách sắp xếp Unicode và utf8mb4_general_ci
đơn giản hóa sắp xếp trong MySQL, nhưng vẫn có một số khác biệt:
-
Ví dụ:đối chiếu Unicode sắp xếp "ß" như "ss" và "Œ" như "OE" như những người sử dụng các ký tự đó thường muốn, trong khi
utf8mb4_general_ci
sắp xếp chúng dưới dạng các ký tự đơn (có lẽ như "s" và "e" tương ứng). -
Một số ký tự Unicode được định nghĩa là có thể bỏ qua, có nghĩa là chúng không được tính vào thứ tự sắp xếp và thay vào đó, phép so sánh sẽ chuyển sang ký tự tiếp theo.
utf8mb4_unicode_ci
xử lý những điều này đúng cách.
Trong các ngôn ngữ không phải tiếng Latinh, chẳng hạn như các ngôn ngữ Châu Á hoặc các ngôn ngữ có các bảng chữ cái khác nhau, có thể có nhiều hơn thế nữa sự khác biệt giữa sắp xếp Unicode và utf8mb4_general_ci
đơn giản hóa sắp xếp. Tính phù hợp của utf8mb4_general_ci
sẽ phụ thuộc nhiều vào ngôn ngữ được sử dụng. Đối với một số ngôn ngữ, nó sẽ khá thiếu sót.
Bạn nên sử dụng gì?
Gần như chắc chắn không có lý do gì để sử dụng utf8mb4_general_ci
nữa, vì chúng tôi đã để lại điểm mà tốc độ CPU đủ thấp để sự khác biệt về hiệu suất sẽ là quan trọng. 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 nút thắt cổ chai khác.
Trước đây, một số người đã khuyến nghị sử dụng utf8mb4_general_ci
ngoại trừ khi việc phân loại chính xác sẽ đủ quan trọng để biện minh cho chi phí hiệu suất. Ngày nay, chi phí hiệu suất đó đã không còn nữa và các nhà phát triển đang coi trọng việc quốc tế hóa hơn.
Có một lập luận được đưa ra rằng nếu tốc độ quan trọng đối với bạn hơn độ chính xác, bạn cũng có thể không thực hiện bất kỳ phân loại nào. Việc tạo ra một thuật toán nhanh hơn nếu bạn không cần nó phải chính xác là điều không cần thiết. Vì vậy, utf8mb4_general_ci
là một thỏa hiệp có thể không cần thiết vì lý do tốc độ và có thể cũng không phù hợp vì lý do chính xác.
Một điều khác mà tôi sẽ nói thêm là ngay cả khi bạn biết ứng dụng của mình chỉ hỗ trợ ngôn ngữ tiếng Anh, nó vẫn có thể cần xử lý tên của mọi người, thường có thể chứa các ký tự được sử dụng trong các ngôn ngữ khác, trong đó điều quan trọng là phải sắp xếp chính xác . Sử dụng các quy tắc Unicode cho mọi thứ giúp bạn thêm yên tâm rằng những người Unicode rất thông minh đã làm việc rất chăm chỉ để sắp xếp hoạt động đúng cách.
Ý nghĩa của các bộ phận
Đầu tiên, ci
dành cho không phân biệt chữ hoa chữ thường phân loại và so sánh. Điều này có nghĩa là nó phù hợp với dữ liệu dạng văn bản và chữ hoa không quan trọng. Các loại đối chiếu khác là cs
(phân biệt chữ hoa chữ thường) cho dữ liệu văn bản trong đó chữ hoa chữ thường là quan trọng và bin
, đối với vị trí mã hóa cần khớp, bit từng bit, phù hợp với các trường là dữ liệu nhị phân được mã hóa thực sự (bao gồm, ví dụ:Base64). Việc sắp xếp phân biệt chữ hoa chữ thường dẫn đến một số kết quả kỳ lạ và so sánh phân biệt chữ hoa chữ thường có thể dẫn đến các giá trị trùng lặp chỉ khác nhau ở dạng chữ cái, do đó, các phép ghép phân biệt chữ hoa chữ thường không được ưa chuộng đối với dữ liệu văn bản - nếu chữ hoa chữ thường quan trọng đối với bạn, thì nếu không thì dấu câu có thể bỏ qua và như vậy có lẽ cũng rất quan trọng và đối chiếu nhị phân có thể thích hợp hơn.
Tiếp theo, unicode
hoặc general
đề cập đến các quy tắc sắp xếp và so sánh cụ thể - cụ thể 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 ngôn ngữ 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 gần đây của MySQL thêm các bộ quy tắc unicode_520
sử dụng các quy tắc từ Unicode 5.2 và 0900
(bỏ phần "unicode_") bằng cách sử dụng các quy tắc từ Unicode 9.0.
Và cuối cùng, utf8mb4
tất nhiên là mã hóa ký tự được sử dụng trong nội bộ. Trong câu trả lời này, tôi chỉ nói về các bảng mã dựa trên Unicode.