Độ dài VARCHAR của MySQL và UTF-8


84

Trong MySQL, nếu tôi tạo một VARCHAR(32)trường mới trong bảng UTF-8, điều đó có nghĩa là tôi có thể lưu trữ 32 byte dữ liệu trong trường đó hoặc 32 ký tự (nhiều byte) không?


@naXa: Tôi không có. Bạn nghĩ tôi nên?
Alix Axel

Tôi không biết.) Đó là câu hỏi của bạn, và nó tùy thuộc vào bạn. Tôi chỉ muốn nói "một câu trả lời khác có vẻ đầy đủ hơn".
naXa

@robsch Câu trả lời được chấp nhận trước đây rất đơn giản và chính xác. Nhưng làm theo yêu cầu phổ biến, tôi đã chấp nhận một trong những bạn muốn.
Alix Axel

Câu trả lời:


168

Câu trả lời này đã xuất hiện ở đầu kết quả tìm kiếm trên google của tôi nhưng không chính xác vì vậy:

Sự nhầm lẫn có thể là do các phiên bản khác nhau của mysql đang được thử nghiệm.

  • Phiên bản 4 tính số byte
  • Phiên bản 5 đếm ký tự

http://dev.mysql.com/doc/refman/5.0/en/string-type-overview.html

MySQL diễn giải các đặc tả độ dài trong định nghĩa cột ký tự theo đơn vị ký tự. (Trước MySQL 4.1, độ dài cột được diễn giải theo byte.) Điều này áp dụng cho các loại CHAR, VARCHAR và TEXT.

Điều thú vị là (tôi chưa nghĩ về nó) độ dài tối đa của một cột varchar bị ảnh hưởng bởi utf8 như sau:

Độ dài tối đa hiệu dụng của một VARCHAR trong MySQL 5.0.3 trở lên tùy thuộc vào kích thước hàng tối đa (65,535 byte, được chia sẻ giữa tất cả các cột) và bộ ký tự được sử dụng. Ví dụ: các ký tự utf8 có thể yêu cầu tối đa ba byte cho mỗi ký tự, vì vậy cột VARCHAR sử dụng bộ ký tự utf8 có thể được khai báo là tối đa 21.844 ký tự.


48
M Brown, cảm ơn vì đã đề cập đến điều này. Trường VARCHAR (10) (sử dụng utf8mb4) có thể lưu trữ "💩💩💩💩💩💩💩💩💩💩" (10 đống poo), đó là 10 ký tự nhưng 40 byte.
6

3
Điều này. Đây là câu trả lời đúng duy nhất. Có quá nhiều người tin rằng hành vi của phiên bản 4 là phúc âm.
Brendan Byrd

2
Câu trả lời được chấp nhận cũng đúng cho MySQL 5 - các số được chèn thực sự là một phần của tập hợp ký tự chiều rộng đầy đủ và là các ký tự unicode nhiều byte, như người đăng cũng đề cập rằng anh ta đã chèn "dữ liệu 32 multibyte". Thật đáng tiếc khi nhiều người đã hiểu lầm.
user193130,

Trích dẫn nguồn sau, tôi tin rằng một ký tự utf8 hiện yêu cầu tối đa 6 byte, vì vậy ở bất kỳ đâu trong khoảng từ 1 đến 6 byte. Điều này gây ra trường hợp xấu nhất cho một ký tự tối đa là 10922. Tôi nghĩ. joelonsoftware.com/articles/Unicode.html
usumoio

1
@usumoio Hiện tại, có vẻ như MySQL sử dụng biến thể 3 byte của UTF-8, với việc di chuyển sang biến thể 4 byte (chuẩn) đang được lên kế hoạch: dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html .
flow2k

8

nó sẽ cho phép bạn lưu trữ 32 ký tự nhiều byte

Để tiết kiệm dung lượng với UTF-8, hãy sử dụng VARCHAR thay vì CHAR. Nếu không, MySQL phải dành riêng ba byte cho mỗi ký tự trong cột utf8 CHAR CHARACTER SET vì đó là độ dài tối đa có thể. Ví dụ: MySQL phải dành 30 byte cho cột CHARACTER SET utf8.

http://dev.mysql.com/doc/refman/5.0/en/charset-unicode.html


Tôi hầu như không bao giờ sử dụng CHARvà khi tôi sử dụng nó không nhằm mục đích lưu trữ các ký tự nhiều byte, vì vậy tôi an toàn. Thế còn VARCHAR, bạn có chắc giới hạn được xác định trong các ký tự nhiều byte chứ không phải trên các ký tự một byte?
Alix Axel

9
@jspcal: UTF-8 sử dụng tối đa 4 byte cho mỗi ký tự, không phải 3. Hay MySQL không hỗ trợ tất cả 4 byte?
Remy Lebeau

4
@RemyLebeau Bạn nói đúng về utf8, nhưng không đúng với MySQL. Các bộ ký tự utf8_xxx khác nhau có kích thước tối đa là 3 byte. Utf8mb4_xxx có 4 ký tự byte. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Buttle Butkus

Với sự phát triển của thời gian, có vẻ như MySQL cuối cùng sẽ sử dụng phiên bản 4 byte tiêu chuẩn (nhưng vẫn chưa có, tại thời điểm viết bài): dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html .
flow2k

6

32 multibyte dữ liệu cho varchar(32)đối chiếu utf8_unicode_ci, tôi vừa thử nghiệm với XAMPP.

1234567890123456789012345678901234567890

Được cắt ngắn thành:

12345678901234567890123456789012

Hãy nhớ rằng đây không phải là các ký tự ASCII thông thường.


4
Trong UTF-8, các ký tự ASCII tiêu chuẩn sẽ chỉ được lưu trữ trong một byte duy nhất - để thực sự kiểm tra điều này, bạn cần thực sự sử dụng một số ký tự multibyte (tức là. Non-ascii) trong phần kiểm tra của bạn.
rjmackay

5
Điều này là sai, ít nhất là đối với MySQL 5+. Khi chỉ định kích thước cột cho varchar hoặc char, nó được chỉ định theo ký tự. Tôi tin rằng kích thước thực của cột VARCHAR (32) sẽ là 32x3 + 1 = 97 byte.
Buttle Butkus

5
@rjmackay '12345' không phải là ký tự ASCII tiêu chuẩn. vi.wikipedia.org/wiki/…
Alexey Lebedev

7
Tôi đã chèn 40 ký tự unicode vào DB và bị cắt bớt 32 ký tự. Nhưng có vẻ như mọi người nghĩ rằng tôi đã sử dụng ascii byte và bị cắt bớt 32 byte. Không có gì lạ, tôi đã nhận được phiếu phản đối, lol.
YOU

2
@ButtleButkus "Tôi tin rằng kích thước thực của cột VARCHAR (32) sẽ là 32x3 + 1 = 97 byte" Điều này sẽ xảy ra nếu bạn sử dụng utf8, nhưng sau đó bạn bị hỏng hỗ trợ Unicode trong MySQL. Bạn nên sử dụng utf8mb4mã hóa thay vào đó, vì có tối đa. 4 byte trong một utf8 char , không phải 3 như trong biến thể của utf8 MySQL của ...
Stijn de Witt

1

Tốt hơn nên sử dụng "char" cho các bảng cập nhật thường xuyên cao vì tổng độ dài dữ liệu của hàng sẽ cố định và nhanh chóng. Các cột Varchar làm cho kích thước dữ liệu hàng động. Điều đó không tốt cho MyISAM, nhưng tôi không biết về InnoDB và những người khác. Ví dụ: nếu bạn có cột "loại" rất hẹp, có thể tốt hơn là sử dụng char (2) với bộ ký tự latin1 để chỉ yêu cầu không gian tối thiểu.


1
Tôi đã đọc rằng nếu BẤT KỲ cột nào trong bảng là varchar, thì bạn sẽ mất tất cả lợi ích của việc có các cột char. Về cơ bản, có vẻ như bạn phải đi với tất cả varchar hoặc tất cả các char trong một bảng để có lợi ích tối đa. Tôi không biết nó có đúng không.
Buttle Butkus

Đối với MyISAM, có một số đối số CHAR. Đối với InnoDB, rất nhiều thứ khác đang diễn ra nên cuộc tranh luận về "kích thước hàng động / cố định" về cơ bản là không liên quan.
Rick James,

IMHO, điểm quan trọng ở đây là đối với độ dài rất nhỏ , nó có thể có lợi khi sử dụng CHAR.
ToolmakerSteve

0

Nếu bạn kết nối với cơ sở dữ liệu bằng cách sử dụng mã hóa latin1 (ví dụ với PHP) để lưu một chuỗi PHP UTF8 trong một cột MySQL UTF8, bạn sẽ có một mã hóa UTF8 kép.

Nếu chuỗi UTF8 dài $s32 ký tự nhưng dài 64 byte và cột là VARCHAR(32)UTF8, thì mã hóa kép sẽ chuyển đổi chuỗi thành chuỗi $sUTF8 dài 64 ký tự sẽ bị cắt ngắn trong cơ sở dữ liệu thành 32 ký tự đầu tiên tương ứng với 32 byte đầu tiên của $s. Bạn có thể nghĩ rằng MySQL 5 hoạt động giống như MySQL 4 nhưng trên thực tế đó là nguyên nhân thứ hai gây ra hiệu ứng tương tự.

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.