UTF-8: Chung? Thùng rác? Unicode?


279

Tôi đang cố gắng tìm ra những đối chiếu nào tôi nên sử dụng cho các loại dữ liệu khác nhau. 100% nội dung tôi sẽ lưu trữ là do người dùng gửi.

Hiểu biết của tôi là tôi nên sử dụng UTF-8 General CI (Case-Insensitive) thay vì UTF-8 Binary. Tuy nhiên, tôi không thể tìm thấy sự khác biệt rõ ràng giữa UTF-8 General CI và UTF-8 Unicode CI.

  1. Tôi có nên lưu trữ nội dung do người dùng gửi trong các cột UTF-8 General hoặc UTF-8 Unicode CI không?
  2. Loại dữ liệu UTF-8 Binary sẽ được áp dụng cho loại dữ liệu nào?

16
Lưu ý bên cạnh nhưng thay vì utf8sử dụng utf8mb4thay thế cho hỗ trợ UTF-8 đầy đủ. Bình luận ở đây vì câu trả lời cho câu hỏi phổ biến này không giải quyết điều này. mathiasbynens.be/notes/mysql-utf8mb4
Steven R. Loomis

Nếu bạn muốn gấp trường hợp, nhưng độ nhạy của dấu, vui lòng gửi yêu cầu tại bug.mysql.com .
Rick James

Hoặc nhấp vào "Ảnh hưởng đến tôi" trên bug.mysql.com/orms.php?id=58797 và thêm nhận xét.
Rick James

Câu trả lời:


299

Nói chung, utf8_general_ci nhanh hơn utf8_unicode_ci , nhưng ít chính xác hơn.

Đây là sự khác biệt:

Đối với bất kỳ bộ ký tự Unicode nào, các thao tác được thực hiện bằng cách đối chiếu _general_ci sẽ nhanh hơn các thao tác đối với đối chiếu _unicode_ci . Ví dụ, so sánh cho đối chiếu utf8_general_ci nhanh hơn, nhưng ít chính xác hơn so với so sánh cho utf8_unicode_ci. Lý do cho điều này là utf8_unicode_ci hỗ trợ ánh xạ như mở rộng; nghĩa là, khi một nhân vật so sánh bằng với sự kết hợp của các nhân vật khác. Ví dụ, trong tiếng Đức và một số ngôn ngữ khác, Tiếng ß là bằng với ss ss. utf8_unicode_ci cũng hỗ trợ các cơn co thắt và các ký tự không thể biết được. utf8_general_ci là một đối chiếu kế thừa không hỗ trợ các bản mở rộng, các cơn co thắt hoặc các ký tự không thể biết được. Nó chỉ có thể thực hiện so sánh một-một giữa các nhân vật.

Trích dẫn từ: http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Để được giải thích chi tiết hơn, vui lòng đọc bài viết sau từ các diễn đàn MySQL: http://forums.mysql.com/read.php?103,187048,188748

Đối với utf8_bin: Cả utf8_general_ciutf8_unicode_ci đều thực hiện so sánh không phân biệt chữ hoa chữ thường. Trong constrast, utf8_bin phân biệt chữ hoa chữ thường (trong số các khác biệt khác), vì nó so sánh các giá trị nhị phân của các ký tự.


2
Tôi nghĩ rằng nếu bạn không có lý do chính đáng để sử dụng _unicode_ci, thì hãy sử dụng _general_ci.
Sagi

4
Điều này không thực sự trả lời câu hỏi sâu. Sự khác biệt giữa các collations chính xác là gì?
Pekka

4
Bạn đã đúng, sự khác biệt chính xác không được cung cấp ở đây vì đơn giản. Tôi đã thêm một liên kết đến một bài viết với sự khác biệt chính xác .
Sagi

NB show collation;cho phép bạn xem đối chiếu mặc định cho từng bộ ký tự. 5.1 hiển thị utf8_general_cinhư mặc định cho utf8.
David Carboni

9
Có tài nguyên nào đi sâu hơn về chênh lệch tốc độ thực tế giữa hai lần va chạm không? Chúng ta đang nói về việc giảm 0,1% hiệu suất hay giảm 10%?
Emphram Stavanger

90

Bạn cũng nên lưu ý rằng, với utf8_general_ci khi sử dụng trường varchar là chỉ mục chính hoặc duy nhất chèn 2 giá trị như 'a' và 'á' sẽ gây ra lỗi khóa trùng lặp.


3
Cảm ơn, điều này hữu ích để tránh các tên người dùng tương tự (ví dụ: nếu "jose" tồn tại, tôi sẽ không muốn người khác tạo người dùng "josé"): điều này cũng đúng với hầu hết các bộ sưu tập utf8 (trừ utf8_bin). Điều chắc chắn nhất / an toàn nhất / toàn diện nhất làutf8_unicode_ci
Costa

2
Tôi sử dụng utf8_bin nơi tôi muốn phân biệt jose và josé trong chỉ mục. Ví dụ: một cột ghi lại các hoạt động tìm kiếm / thay thế, trong đó người dùng có thể đã quyết định tìm kiếm josé và thay thế nó bằng jose. (Tôi đang viết một chương trình bảng tính)
Butussy Butkus

33
  • utf8_binso sánh các bit một cách mù quáng. Không có trường hợp gấp, không có dấu nhấn.
  • utf8_general_ciso sánh một byte với một byte. Nó không gấp tách dấu, nhưng không có so sánh 2 ký tự: ijkhông bằng ijtrong đối chiếu này.
  • utf8_*_cilà một tập hợp các quy tắc dành riêng cho ngôn ngữ, nhưng nếu không thì thích unicode_ci. Một số trường hợp đặc biệt: Ç, Č, ch,ll
  • utf8_unicode_citheo một tiêu chuẩn Unicode cũ để so sánh. ij= ij, nhưng ae! =æ
  • utf8_unicode_520_cituân theo một tiêu chuẩn Unicode mới hơn. ae= =æ

Xem biểu đồ đối chiếu để biết chi tiết về những gì bằng với những gì trong các bộ sưu tập utf8 khác nhau.

utf8, như được định nghĩa bởi MySQL được giới hạn ở các mã utf8 1 đến 3 byte. Điều này bỏ qua Emoji và một số người Trung Quốc. Vì vậy, bạn nên thực sự chuyển sang utf8mb4nếu bạn muốn đi xa hơn châu Âu.

Các điểm trên áp dụng cho utf8mb4, sau khi thay đổi chính tả phù hợp. Đi về phía trước, utf8mb4utf8mb4_unicode_520_ciđược ưa thích.

  • utf16 và utf32 là các biến thể trên utf8; hầu như không sử dụng chúng.
  • ucs2 gần với "Unicode" hơn "utf8"; hầu như không sử dụng cho nó.

1
Re "hãy theo dõi": 8.0 collations cho thấy các nhân vật khác nhau, diphthongs, v.v., so sánh như thế nào trong các collations 8.0 utf8mb4; utf8 hầu hết đều giống nhau.
Rick James

Và 8.0 collations được tốc độ nhanh hơn đáng kể so với 5.x.
Rick James

Sẽ thật tuyệt nếu trang đó liệt kê utf8mb4_bin ở đầu trang. Tôi biết nó hoàn toàn không phù hợp với nhân vật, nhưng nó tốt cho người mới.
Henk Poley

6

Thực sự, tôi đã thử nghiệm các giá trị lưu như 'é' và 'e' trong cột với chỉ mục duy nhất và chúng gây ra lỗi trùng lặp trên cả 'utf8_unicode_ci' và 'utf8_general_ci'. Bạn chỉ có thể lưu chúng trong cột đối chiếu 'utf8_bin'.

Và các tài liệu mysql (trong http://dev.mysql.com/doc/refman/5.7/en/charset-appluggest.html ) đề xuất vào các ví dụ của nó đặt đối chiếu 'utf8_general_ci'.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

1
Tôi đã làm một bài kiểm tra nhanh về điều này, và nó có vẻ chính xác. Cả hai collations hoạt động giống nhau khi nói đến một khóa duy nhất trên một cột và các giá trị với dấu ngã và tương tự.
MirroredFate

@MirroredFate OK, tôi nên thêm vào đó cột đó nên có chỉ mục duy nhất để gây ra lỗi này. Nó ngụ ý trong câu trả lời của tôi.
Vitalii

3

Câu trả lời được chấp nhận là lỗi thời.

Nếu bạn sử dụng MySQL 5.5.3+, hãy sử dụng utf8mb4_unicode_cithay vì utf8_unicode_ciđể đảm bảo các ký tự được người dùng nhập vào sẽ không gây ra lỗi cho bạn.

utf8mb4hỗ trợ biểu tượng cảm xúc chẳng hạn, trong khi utf8có thể cung cấp cho bạn hàng trăm lỗi liên quan đến mã hóa như:

Incorrect string value: ‘\xF0\x9F\x98\x81…’ for column ‘data’ at row 1


Câu trả lời này (chính xác) giải quyết các vấn đề về mã hóa Emoji (và một số tiếng Trung Quốc). Nhưng Câu hỏi dường như tập trung vào Collation. utf8mb4_unicode_ciđối xử (tôi nghĩ) tất cả các Emoji là như nhau. utf8mb4_unicode_520_cira lệnh cho Emoji.
Rick James
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.