Có sự khác biệt về hiệu suất trong MySQL giữa các kích thước varchar không? Ví dụ, varchar(25)
và varchar(64000)
. Nếu không, có lý do gì để không khai báo tất cả các varvar với kích thước tối đa chỉ để đảm bảo bạn không hết phòng?
Có sự khác biệt về hiệu suất trong MySQL giữa các kích thước varchar không? Ví dụ, varchar(25)
và varchar(64000)
. Nếu không, có lý do gì để không khai báo tất cả các varvar với kích thước tối đa chỉ để đảm bảo bạn không hết phòng?
Câu trả lời:
Bạn phải nhận ra sự đánh đổi bằng cách sử dụng CHAR vs VARCHAR
Với các trường CHAR, những gì bạn phân bổ chính xác là những gì bạn nhận được. Ví dụ: CHAR (15) phân bổ và lưu trữ 15 byte, bất kể bạn đặt ký tự trong trường như thế nào. Thao tác chuỗi rất đơn giản và dễ hiểu vì kích thước của trường dữ liệu là hoàn toàn có thể dự đoán được.
Với các trường VARCHAR, bạn có được một câu chuyện hoàn toàn khác. Ví dụ, VARCHAR (15) thực sự phân bổ động tối đa 16 byte, tối đa 15 cho dữ liệu và, ít nhất, thêm 1 byte để lưu trữ độ dài của dữ liệu. Nếu bạn có chuỗi 'hello' để lưu trữ sẽ mất 6 byte, chứ không phải 5. Thao tác chuỗi phải luôn thực hiện một số hình thức kiểm tra độ dài trong mọi trường hợp.
Sự cân bằng thể hiện rõ hơn khi bạn thực hiện hai điều:
1. Lưu trữ hàng triệu hoặc hàng tỷ hàng
2. Các cột lập chỉ mục là CHAR hoặc VARCHAR
Rõ ràng, VARCHAR nắm giữ lợi thế vì dữ liệu có độ dài thay đổi sẽ tạo ra các hàng nhỏ hơn và do đó, các tệp vật lý nhỏ hơn.
Do các trường CHAR yêu cầu thao tác chuỗi ít hơn do độ rộng trường cố định, tra cứu chỉ mục so với trường CHAR trung bình nhanh hơn 20% so với trường VARCHAR. Đây không phải là bất kỳ phỏng đoán nào về phía tôi. Cuốn sách Thiết kế và điều chỉnh cơ sở dữ liệu MySQL đã thực hiện một cái gì đó tuyệt vời trên bảng MyISAM để chứng minh điều này. Ví dụ trong cuốn sách đã làm một cái gì đó như sau:
ALTER TABLE tblname ROW_FORMAT=FIXED;
Các lực lượng chỉ thị này là VARCHAR để hành xử như CHARs. Tôi đã làm điều này trong công việc trước đây vào năm 2007 và lấy một bảng 300 GB và tăng tốc độ tra cứu chỉ số thêm 20% mà không thay đổi bất cứ điều gì khác. Nó làm việc như đã xuất bản. Tuy nhiên, nó đã tạo ra một bảng có kích thước gần gấp đôi, nhưng điều đó chỉ đơn giản là quay trở lại sự đánh đổi # 1.
Bạn có thể phân tích dữ liệu đang được lưu trữ để xem những gì MySQL đề xuất cho định nghĩa cột. Chỉ cần chạy như sau với bất kỳ bảng nào:
SELECT * FROM tblname PROCEDURE ANALYSE();
Điều này sẽ đi qua toàn bộ bảng và đề xuất các định nghĩa cột cho mỗi cột dựa trên dữ liệu chứa, các giá trị trường tối thiểu, giá trị trường tối đa, v.v. Đôi khi, bạn chỉ cần sử dụng thông thường với việc lập kế hoạch CHAR vs VARCHAR. Đây là một ví dụ tốt:
Nếu bạn đang lưu trữ địa chỉ IP, mặt nạ cho một cột như vậy nhiều nhất là 15 ký tự (xxx.xxx.xxx.xxx). Tôi sẽ nhảy ngay tại CHAR (15) trong một nhịp tim vì độ dài của địa chỉ IP sẽ không thay đổi nhiều và độ phức tạp thêm của thao tác chuỗi được điều khiển bởi một byte bổ sung. Bạn vẫn có thể thực hiện PHÂN TÍCH THỦ TỤC () đối với một cột như vậy. Nó thậm chí có thể đề nghị VARCHAR. Tiền của tôi vẫn sẽ có trên CHAR trên VARCHAR trong trường hợp này.
Các vấn đề CHAR vs VARCHAR chỉ có thể được giải quyết thông qua kế hoạch thích hợp. Với sức mạnh lớn đi kèm với trách nhiệm lớn (sáo rỗng nhưng có thật)
Câu trả lời cho điều này thực sự khá phức tạp. Phiên bản ngắn: có một sự khác biệt .
Khi tạo các bảng tạm thời để lọc kết quả (ví dụ: các GROUP BY
câu lệnh), toàn bộ chiều dài sẽ được phân bổ.
Giao thức dây (gửi hàng đến máy khách) có thể sẽ phân bổ chiều dài lớn hơn.
Công cụ lưu trữ có thể / có thể không thực hiện một varchar thích hợp.
Đối với (2) Tôi thừa nhận giao thức dây không phải là thứ tôi quen thuộc, nhưng lời khuyên chung ở đây là thử và áp dụng ít nhất một số nỗ lực tối thiểu để đoán độ dài.
Hầu hết các câu trả lời trong chủ đề này là 5 tuổi, được viết trước khi InnoDB và utf8 được mặc định. Vì vậy, hãy để tôi bắt đầu lại ...
Khi một truy vấn cần một bảng tạm thời nội bộ, nó cố gắng sử dụng một MEMORY
bảng. Nhưng NHỚ không thể được sử dụng nếu
TEXT
/ BLOB
cột được tìm nạp, thậm chí không TINYTEXT
.VARCHAR
lớn hơn một số tiền, có thể là 512 trong phiên bản hiện tại.Ngoài ra, lưu ý rằng VARCHARs
được biến thành CHARs
. Vì vậy, VARCHAR(255)
với việc CHARACTER SET utf8
mở rộng tới 765 byte, bất kể những gì trong cột. Sau đó, điều này có thể được kích hoạt:
MEMORY
bảng được lớn hơn hoặc max_heap_table_size
hay tmp_table_size
, nó sẽ được chuyển đổi sang MyISAM và có khả năng đổ vào đĩa.Vì vậy, VARCHAR(25)
có nhiều khả năng ở lại MEMORY
, do đó được nhanh hơn. (255)
không phải là tốt, và (64000)
là xấu.
(Trong tương lai, các bảng tạm thời có thể sẽ có InnoDB
, và một phần của câu trả lời này sẽ cần sửa đổi.)
Một cột varchar có kích thước làm cho các truy vấn trên toàn bộ bảng có nhiều khả năng sử dụng các bảng tạm thời. Theo sách MySQL hiệu suất cao. Khi trình tối ưu hóa thử xem liệu nó có thể chạy truy vấn này trong bộ nhớ hay nếu nó cần một bảng tạm thời, nó sẽ xem kích thước hàng dựa trên định nghĩa bảng, nghĩa là, về tốc độ, nó không cố gắng xem bao nhiêu trong số 64K ký tự bạn đang thực sự sử dụng. Đây là lý do tại sao các nhà văn khuyên bạn không nên mở rộng cách định nghĩa đó vượt ra ngoài các giá trị thực tế có thể có trong cột. Rõ ràng, nếu bạn tự đặt cho mình nhiều truy vấn hơn vào các bảng tạm thời (ngay cả khi kích thước dữ liệu thực tế có thể vừa với RAM), bạn đã phải chịu các hình phạt I / O mà bạn có thể tránh được.
Theo hiểu biết của tôi, các trường nhỏ hơn có thể được đưa vào chỉ mục trực tiếp, trong khi các trường dài hơn thì không thể. Do hạn chế đó, nếu bạn muốn các chuỗi có thể lập chỉ mục, tôi sẽ nói giữ chúng ngắn hơn. Mặt khác, không, giống như cách cả hai varchar sau đó hoạt động như sắp xếp hoặc so sánh sẽ hoạt động như thời gian, cho dù các trường là 25 hay MAX.
đảm bảo bạn không hết phòng
Cụm từ này ngụ ý rằng bạn đặt câu hỏi vì bạn không chắc chắn về dữ liệu bạn sẽ lưu trữ trong cơ sở dữ liệu. Nếu đó là sự thật, bạn sẽ được phục vụ tốt để tìm hiểu ngay khi bạn có thể, bởi vì bạn sẽ cần điều đó để lập kế hoạch năng lực. Ví dụ, nếu bạn có thể nhận được các phần tử dữ liệu với 7000 ký tự, bạn cần biết vì điều đó sẽ có ý nghĩa về hiệu suất trên bất kỳ DBMS nào.
Điều đó nói rằng, tôi thích có kích thước cột liên quan đến nội dung dự kiến. Ví dụ: số điện thoại không có khả năng dài hơn 50 ký tự, ngay cả khi bạn bao gồm mã quốc gia và tiện ích mở rộng. Tương tự, mã zip hoặc mã bưu chính rất có thể sẽ có 20 ký tự hoặc ít hơn.