Tầm quan trọng của độ dài varchar trong bảng MySQL


112

Tôi có một bảng MySQL nơi các hàng được chèn động. Bởi vì tôi không thể chắc chắn về độ dài của các chuỗi và không muốn chúng bị cắt bỏ, tôi làm cho chúng varchar (200) nói chung là lớn hơn nhiều so với mức tôi cần. Có một hiệu suất lớn khi cung cấp cho trường varchar có độ dài nhiều hơn mức cần thiết không?


Một bảng có một VARCHAR(255) utf8mb4cột được lập chỉ mục với ~ 150 nghìn hàng được đo là 11,5 MB. Một bảng có VARCHAR(48) utf8mb4cột được lập chỉ mục có cùng dữ liệu (độ dài tối đa 46 ký tự) được sử dụng 4,5 MB. Không thực sự khác biệt lớn trong các truy vấn, nó được lập chỉ mục. Nhưng nó kết hợp với I / O truy vấn và những thứ như sao lưu cơ sở dữ liệu.
Code4R7

Câu trả lời:


59

Không, theo nghĩa là nếu các giá trị bạn đang lưu trữ trong cột đó luôn (giả sử) ít hơn 50 ký tự, thì việc khai báo cột là varchar(50)hoặc varchar(200)có cùng hiệu suất.


9
Không hẳn là sự thật. Xem câu trả lời của Bill Karwin
hejdav

5
Tôi nghĩ rằng một câu trả lời như nên được hỗ trợ bởi tài liệu, điểm chuẩn hoặc thứ gì đó tương tự.
Gokhan Sari

301

Có thể có một tác động đến hiệu suất: trong MySQL, các bảng và bảng tạm thời MEMORYlưu trữ một VARCHARcột dưới dạng cột có độ dài cố định, được đệm đến độ dài tối đa của nó. Nếu bạn thiết kế VARCHARcác cột lớn hơn nhiều so với kích thước lớn nhất mà bạn cần, bạn sẽ tiêu tốn nhiều bộ nhớ hơn những gì bạn có. Điều này ảnh hưởng đến hiệu quả bộ nhớ cache, tốc độ sắp xếp, v.v.


33
+1. Tôi cũng có vẻ như một số trình điều khiển JDBC phân bổ đủ không gian cho kích thước tối đa khi thiết lập bộ đệm để truy xuất hàng. Không cần phải nói, điều này gây ra nhiều cảm giác lo lắng và nghiến răng khi một số chú hề vừa thực hiện varchar (50000) chỉ trong trường hợp một người nào đó có một cái tên cuối cùng thực sự lớn :-)
paxdiablo

21
+1. Đây là một tác động quan trọng và tôi tin rằng đây là câu trả lời thực sự của câu hỏi này.
Emre Yazici

6
Câu trả lời này và câu trả lời được chấp nhận đều cần thiết để hiểu câu trả lời chính xác cho OP.
kd8azz

2
Trên thực tế, khi một MEMORYbảng như vậy được coi là quá lớn, nó sẽ được ghi vào đĩa, gây ra sự suy giảm hiệu suất đáng kể.
Timo

1
Câu trả lời này có thể thực hiện với việc chỉ định công cụ lưu trữ nào là đúng (Tôi lưu ý rằng dev.mysql.com/doc/refman/8.0/en/… chỉ ra rằng các bảng tạm thời luôn là InnoDB kể từ MySQL 8; điều đó có thay đổi gì không?) và với các liên kết tới tài liệu sao lưu các tuyên bố mà nó đưa ra. Từ những gì tôi đã thấy về đầu ra của bạn trên Stack Exchange, tôi tin rằng bạn đã đúng khi viết điều này, nhưng mọi thứ có thể đã thay đổi và các liên kết sẽ là một ví dụ tốt cho những người khác và giúp dạy những người còn lại trong chúng ta tìm loại thông tin này cho chính chúng ta.
Mark Amery

14

VARCHAR là lý tưởng cho tình huống bạn mô tả, bởi vì nó là viết tắt của "ký tự biến" - giới hạn, dựa trên ví dụ của bạn, sẽ là 200 ký tự nhưng bất kỳ thứ gì ít hơn được chấp nhận sẽ không lấp đầy kích thước được phân bổ của cột.

VARCHAR cũng chiếm ít dung lượng hơn - các giá trị được lưu trữ dưới dạng tiền tố độ dài một byte hoặc hai byte cộng với dữ liệu. Tiền tố độ dài cho biết số byte trong giá trị. Một cột sử dụng một byte độ dài nếu giá trị yêu cầu không quá 255 byte, hai byte độ dài nếu giá trị có thể yêu cầu nhiều hơn 255 byte.

Để biết thêm thông tin so sánh kiểu dữ liệu MySQL CHAR với VARCHAR, hãy xem liên kết này .


1
mọi người quan tâm đến lưu trữ MySQL (về CHAR và VARCHAR) nên đọc liên kết được đề cập trong câu trả lời này. Cảm ơn!
Pascal

14

Kích thước là hiệu suất! Kích thước càng nhỏ càng tốt. Không phải hôm nay hay ngày mai, mà là một ngày nào đó, những chiếc bàn của bạn sẽ trở nên lớn mạnh khi gặp phải những tắc nghẽn nghiêm trọng, bất kể bạn đã đặt ra thiết kế nào. Nhưng bạn có thể thấy trước một số tắc nghẽn tiềm ẩn trong giai đoạn thiết kế của bạn có khả năng xảy ra trước tiên và cố gắng mở rộng thời gian db của bạn sẽ hoạt động nhanh chóng và vui vẻ cho đến khi bạn cần suy nghĩ lại kế hoạch của mình hoặc mở rộng quy mô theo chiều ngang bằng cách thêm nhiều máy chủ hơn.

Trong trường hợp của bạn, có nhiều rò rỉ hiệu suất mà bạn có thể gặp phải: Các liên kết lớn gần như không thể với varcharcác cột dài . Lập chỉ mục trên các cột đó là một kẻ giết người thực sự. Đĩa của bạn phải lưu trữ dữ liệu. Một trang bộ nhớ có thể chứa ít hàng hơn và quá trình quét bảng sẽ chậm hơn nhiều. Ngoài ra, bộ nhớ cache truy vấn sẽ không thể giúp bạn ở đây.

Bạn phải tự hỏi mình: Có bao nhiêu lần chèn mỗi năm? Chiều dài trung bình là gì? Tôi có thực sự cần nhiều hơn 200 ký tự hay tôi có thể nắm bắt được điều đó trong giao diện người dùng ứng dụng của mình, ngay cả khi thông báo cho người dùng về độ dài tối đa? Tôi có thể chia bảng thành một bảng hẹp để lập chỉ mục và quét nhanh và một bảng khác để chứa dữ liệu bổ sung, ít thường xuyên cần thiết hơn với kích thước mở rộng không? Tôi có thể nhập dữ liệu varchar có thể có vào các danh mục và do đó trích xuất một số dữ liệu thành một vài cột nhỏ hơn, có thể là kiểu int hoặc kiểu bool và thu hẹp cột varchar theo cách đó không?

Bạn có thể làm rất nhiều ở đây. Tốt nhất có thể là giả định đầu tiên và sau đó thiết kế lại từng bước bằng cách sử dụng dữ liệu hiệu suất đo được trong đời thực. Chúc may mắn.


+1 để liệt kê các tùy chọn thiết kế và khám phá tác động. Rất hữu ích cho câu hỏi của tôi. stackoverflow.com/q/12083089/181638
Assad Ebrahim

5
Có bất kỳ tác động thực tế nào đến hiệu suất từ ​​việc đặt độ dài tối đa cao hay hiệu suất chỉ được xác định bởi kích thước thực?
poolie

5

Hiệu suất? Không. Ổ đĩa lưu trữ? Có, nhưng nó rẻ và phong phú. Trừ khi cơ sở dữ liệu của bạn sẽ phát triển đến quy mô terabyte, bạn có thể không sao.


Kỳ lạ là câu trả lời này đã bị phản đối sáu năm sau khi nó được đăng và không có câu trả lời nào khác. Có vẻ thù dai và nhỏ nhen. Không có gì sai về câu trả lời này. Người điều hành?
duffymo

1
Như đã nói, nó ảnh hưởng đến hiệu suất. Ngoài ra, ổ lưu trữ cũng không miễn phí. Một cột rộng hơn có nghĩa là nhiều đĩa đọc / ghi hơn (và quyền truy cập đĩa là slooooooow), và các chỉ mục cũng rộng hơn, điều này làm giảm tính hữu dụng của chúng. Cả hai điều này đều tác động tiêu cực đến hiệu suất. Có thể điều đó không đáng kể trên một cơ sở dữ liệu nhỏ, nhưng trên quy mô gigabyte / terabyte thì chắc chắn nó sẽ có vấn đề, như bạn nói. Đối với một bảng đăng ký 100, nó không quan trọng.
Alejandro

5

Một số bạn đang nhầm tưởng rằng a varchar(200)chiếm nhiều kích thước bảng trên đĩa hơn a varchar(20). Đây không phải là trường hợp. Chỉ khi bạn vượt quá 255 ký tự thì mysql mới sử dụng thêm một byte để xác định độ dài của varchardữ liệu trường.


9
Không phải như vậy đối với bảng và bảng tạm thời MEMORY.
Lightness Races in Orbit

4
Bất cứ khi nào truy vấn chọn của bạn sử dụng một bảng tạm thời (nhóm và sắp xếp theo các phép toán, trong số những thứ khác), nó sẽ chuyển đổi varchar (200) thành char (200) và hiệu suất sẽ bị ảnh hưởng.
Jamie

1

Có thể có số lần truy cập hiệu suất - nhưng thường không ở mức mà hầu hết người dùng sẽ nhận thấy.

Khi kích thước của mỗi trường được biết trước, MySQL biết chính xác có bao nhiêu byte giữa mỗi trường / hàng và có thể chuyển tiếp trang mà không cần đọc tất cả dữ liệu. Sử dụng các ký tự biến sẽ làm giảm khả năng này để tối ưu hóa.

Varchar có dẫn đến việc đạt hiệu suất do phân mảnh dữ liệu không?

Thậm chí tốt hơn, char vs varchar .

Đối với hầu hết sử dụng, bạn sẽ bị phạt với một trong hai - nhưng có một sự khác biệt, và cho cơ sở dữ liệu quy mô lớn, có những lý do tại sao bạn muốn chọn một hay cách khác.


0

Là varchar, thay vì chỉ char, kích thước dựa trên một trường bên trong để chỉ ra chiều dài thực của nó và chính chuỗi. Vì vậy, sử dụng varchar (200) không khác lắm so với sử dụng varchar (150), ngoại trừ việc bạn có khả năng lưu trữ nhiều hơn.

Và bạn nên xem xét những gì xảy ra trên một bản cập nhật, khi một hàng tăng lên. Nhưng nếu điều này là hiếm, thì bạn sẽ ổn.


0

Theo tên loại dữ liệu cho thấy đây là VARCHAR tức là bộ lưu trữ dữ liệu ký tự biến đổi, công cụ mysql tự phân bổ bộ nhớ đang được sử dụng theo dữ liệu được lưu trữ, vì vậy theo hiểu biết của tôi thì không có hiệu suất nào.


0

Bạn nên cố gắng xem một cột varchar giống như bạn xem một cột char trong hầu hết các trường hợp và đặt độ dài một cách thận trọng. Bạn không cần phải luôn nghĩ đến var modifier như một thứ ảnh hưởng đến việc đưa ra quyết định của bạn về độ dài tối đa. Nó thực sự nên được xem như một gợi ý hiệu suất thay vì các chuỗi được cung cấp sẽ có độ dài khác nhau.

Nó không phải là một chỉ thị phải được tuân thủ nghiêm ngặt bởi nội bộ cơ sở dữ liệu, nó có thể hoàn toàn bị bỏ qua. Tuy nhiên, hãy cẩn thận với điều này vì đôi khi việc triển khai có thể bị rò rỉ (ví dụ: chiều dài cố định và phần đệm) mặc dù nó không nên trong một thế giới lý tưởng.

Nếu bạn có varchar (255) thì bạn không có gì đảm bảo rằng hiệu suất khôn ngoan, nó sẽ luôn hoạt động khác với char (255) trong mọi trường hợp.

Có thể dễ dàng đặt nó ở một cái gì đó chẳng hạn như 255, 65535, v.v. theo lời khuyên được đưa ra trong sách hướng dẫn về yêu cầu lưu trữ. Điều này tạo ấn tượng rằng bất kỳ giá trị nào giữa 0 (vâng, đó là một điều) và 255 sẽ có cùng tác động. Tuy nhiên đó không phải là điều có thể được đảm bảo hoàn toàn.

Các yêu cầu lưu trữ có xu hướng đúng hoặc là một chỉ báo tốt cho các công cụ lưu trữ ổn định và trưởng thành về mặt lưu trữ hàng. Nó không phải là một chỉ báo mạnh cho những thứ như chỉ mục.

Đôi khi nó là một câu hỏi khó, chính xác thì một đoạn dây sẽ dài bao nhiêu để thiết lập nó thành giới hạn cao nhất mà bạn biết là nó phải ở trong đó nhưng điều đó không có tác động. Thật không may, đây thường là thứ để người dùng giải quyết và nó thực sự hơi tùy tiện. Bạn thực sự không thể nói không bao giờ vượt quá kích thước một chuỗi vì có thể có những trường hợp bạn không chắc chắn chính xác.

Bạn nên đảm bảo rằng các truy vấn MySQL phát ra lỗi khi một chuỗi quá dài thay vì cắt bớt để ít nhất bạn biết liệu nó có thể quá ngắn khi phát ra lỗi hay không. Thay đổi kích thước cột để phóng to hoặc thu nhỏ chúng có thể là một hoạt động DDL tốn kém, điều này cần được ghi nhớ.

Bộ ký tự cũng nên được xem xét khi độ dài và hiệu suất phát huy tác dụng. Độ dài đề cập đến điều này thay vì byte. Nếu sử dụng utf8 chẳng hạn, (không phải MB4) thì varchar (255) thực sự là varbinary (3 * 255). Thật khó để biết những thứ như thế này sẽ thực sự diễn ra như thế nào nếu không chạy các bài kiểm tra và tìm hiểu sâu về mã nguồn / tài liệu. Bởi vì điều này có phạm vi cho chiều dài quá mức để có tác động thổi phồng bất ngờ. điều này không chỉ áp dụng cho hiệu suất. Nếu một ngày nào đó bạn cần thay đổi bộ ký tự của cột varchar thành một cột lớn hơn thì bạn có thể đạt đến một giới hạn nào đó mà không cần truy đòi nếu bạn cho phép các chuỗi dài vô cớ xuất hiện mà điều này có thể tránh được. Đây bình thường là một vấn đề khá thích hợp nhưng nó sẽ xuất hiện,

Nếu nó chỉ ra rằng MAX (LENGTH (cột)) luôn <64 (chẳng hạn như nếu nó được quyết định sẽ có giới hạn về đầu vào không được khớp với định nghĩa cột) nhưng bạn có varchar (255) thì có một rất có thể bạn sẽ sử dụng dung lượng gấp bốn lần so với mức cần thiết trong một số trường hợp.

Điều này có thể bao gồm:

  • Các động cơ khác nhau, một số có thể bỏ qua nó hoàn toàn.
  • Kích thước bộ đệm, ví dụ cập nhật hoặc chèn có thể phải phân bổ 255 đầy đủ (mặc dù tôi chưa kiểm tra mã nguồn để chứng minh điều này, đó chỉ là giả thuyết).
  • Chỉ mục, điều này sẽ rõ ràng ngay lập tức nếu bạn cố gắng tạo một khóa tổng hợp từ nhiều cột varchar (255).
  • Bảng trung gian và có thể cả tập kết quả. Với cách thức hoạt động của giao dịch, có thể không phải lúc nào thứ gì đó cũng có thể sử dụng độ dài tối đa thực tế của các chuỗi trong một cột trái ngược với giới hạn đã xác định.
  • Các tối ưu hóa dự đoán nội bộ có thể lấy độ dài tối đa làm đầu vào.
  • Các thay đổi trong các phiên bản triển khai cơ sở dữ liệu.

Theo nguyên tắc chung, thực sự không cần một varchar dài hơn mức cần thiết, các vấn đề về hiệu suất hay không, vì vậy tôi khuyên bạn nên tuân theo điều đó khi bạn có thể. Cố gắng nhiều hơn để lấy mẫu kích thước dữ liệu của bạn, thực thi một giới hạn thực sự hoặc tìm ra giới hạn thực sự thông qua yêu cầu / nghiên cứu là cách tiếp cận lý tưởng.

Khi bạn không thể, nếu bạn muốn làm điều gì đó chẳng hạn như varchar (255) cho các trường hợp nghi ngờ thì tôi khuyên bạn nên làm theo khoa học. Điều này có thể bao gồm việc sao chép bảng, giảm kích thước của cột var char sau đó sao chép dữ liệu vào đó từ bản gốc và xem kích thước của dữ liệu chỉ mục / hàng (cũng lập chỉ mục cột, cũng có thể thử nó làm khóa chính. có thể hoạt động khác trong InnoDB vì các hàng được sắp xếp theo khóa chính). Ít nhất bằng cách này, bạn sẽ biết liệu bạn có tác động đến IO, vốn có xu hướng là một trong những nút thắt nhạy cảm nhất. Kiểm tra mức độ sử dụng bộ nhớ khó hơn, thật khó để kiểm tra toàn bộ. Tôi khuyên bạn nên thử nghiệm các trường hợp xấu nhất có thể xảy ra (các truy vấn có nhiều kết quả trung gian trong bộ nhớ, kiểm tra với giải thích cho các bảng tạm thời lớn, v.v.).

Nếu bạn biết rằng sẽ không có nhiều hàng trong bảng, bạn sẽ không sử dụng cột cho các phép nối, chỉ mục (đặc biệt là tổng hợp, duy nhất), v.v. thì rất có thể bạn sẽ không gặp nhiều vấ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.