Ý nghĩa về hiệu suất của các kích thước VARCHAR của MySQL


45

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)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?


3
+1 câu hỏi này áp dụng tương tự cho tất cả DBMS. Quan sát của tôi nhiều kích thước varchar có xu hướng phát triển.
bernd_k

5
Không phải MySQL, nhưng bài đăng trên blog này của Depesz có thể trả lời câu hỏi của bạn cho PostgreSQL .
xenoterracide

Câu trả lời:


29

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

THƯƠNG MẠI # 1

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.

THƯƠNG MẠI # 2

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)


4
Nếu bạn lưu trữ địa chỉ IP, tôi thấy không có lý do gì để lưu trữ chúng dưới dạng int. Đó là tất cả địa chỉ IP. Nhiều ngôn ngữ có một số loại chức năng ip2int. Nếu bạn muốn sự liên tục của một dòng lệnh gọi, không khó để thực hiện một thủ tục được lưu trữ để chuyển đổi ABCD: A pow (256,3) + b pow (256,2) + c * 256 + d
atxdba

1
Thêm nữa, tôi đoán mysql có chức năng ip2int của riêng nó: INET_ATON
atxdba

3
@atxdba: Điểm của câu trả lời của tôi chỉ là sử dụng CHAR vs VARCHAR. Tôi chỉ sử dụng IP làm ví dụ vì kích thước ký tự chuỗi của nó gần bằng 15. Do đó, làm tròn kích thước CHAR ổn định có lợi cho VARCHAR chỉ là một ví dụ cho chính câu hỏi. Nhận xét của bạn về các cách tốt hơn để thể hiện địa chỉ IP là khá hợp lệ và có ý nghĩa nhất.
RolandoMySQLDBA

CHAR (15) phân bổ 15 ký tự , không phải byte . Đối với utf8, đó là 45 byte .
Rick James

2
Mặc dù đây là một câu trả lời tốt về so sánh CHAR / VARCHAR, câu hỏi là về các kích thước VARCHAR khác nhau.
Nhà sưu tập

13

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 .

  1. Khi tạo các bảng tạm thời để lọc kết quả (ví dụ: các GROUP BYcâu lệnh), toàn bộ chiều dài sẽ được phân bổ.

  2. 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.

  3. 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.


Đáng để chỉ ra. MySQL 5.7 có thể đóng gói các giá trị trong bộ đệm sắp xếp (độ dài thay đổi). Giải thích chi tiết hơn tại đây: mysqlserverteam.com/ từ
Morgan Tocker 7/214

9

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 MEMORYbảng. Nhưng NHỚ không thể được sử dụng nếu

  • TEXT/ BLOBcộ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 utf8mở 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:

  • Nếu MEMORYbả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.)


6

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.


Đó là một viễn cảnh rất mới mẻ. Nếu đây là cuốn sách mà bạn đang đề cập đến ( amazon.com/MySQL-High-Availability-Building-Centers/dp/... ), xin vui lòng đặt số trang của cuốn sách trong câu trả lời của bạn, bởi vì tôi muốn đọc đó. +1 !!!
RolandoMySQLDBA

Silly me lòng HIỆU SUẤT cao không có sẵn: amazon.com/High-Performance-MyQuery-Optimization-Replication/dp/ số trang của Trang là 236/237 Nó giải thích cách hào phóng trong việc xác định cột varchar có thể không khôn ngoan. Hãy ghi nhớ rằng cuốn sách này đã được viết lại khi 5.1 vừa ra mắt. Phiên bản thứ ba sẽ ra mắt vào năm tới để bao gồm tất cả các thay đổi LỚN trong 5.5 vì vậy có thể điều đó sẽ thay đổi :)
TechieGurl

Trang 236 đề cập đối chiếu thuộc các bộ char cụ thể. Điều đó có thể gây khó chịu cho VARCHAR. Trên trang 237, Cài đặt cho liên lạc máy khách / máy chủ cùng với Hình 5-5 trên trang 238 cho thấy một lý do khác. Quá trình dịch bộ ký tự qua lại. Một lần nữa, một cuộc phiêu lưu khó chịu khác cho VARCHAR.
RolandoMySQLDBA

Để làm rõ, mặc dù phần này không nói rõ rằng MySQL sẽ tạo kích thước, chúng tôi biết rằng khi một thao tác cần một bảng tạm thời trong MEMOR Engine và THAT luôn lưu trữ các kiểu chuỗi trong các bản sửa lỗi, đó là cách hào phóng định nghĩa có thể khiến bảng tạm thời NHỚ cần thiết vào đĩa thay vì lưu lại trong RAM
TechieGurl

@RolandoMyQueryDBA. Có thể đối chiếu quá giống nhau cũng trở thành một yếu tố ở đây (đặc biệt nếu bạn sử dụng UTF-8 và không có ký tự không phải là tiếng Latin) và tất cả chỉ giết chết bạn khi xử lý bảng công cụ bộ nhớ và dẫn đến một chuyến đi nhanh hơn vào đĩa
TechieGurl

5

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.


3

đả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.

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.