Tại sao không sử dụng varchar (max)?


76

Tôi hơi cũ khi nói đến thiết kế cơ sở dữ liệu, vì vậy tôi hoàn toàn thích sử dụng kích thước dữ liệu chính xác trong các cột. Tuy nhiên, khi xem lại cơ sở dữ liệu cho một người bạn, tôi nhận thấy anh ấy đã sử dụng varchar(max)rất nhiều. Bây giờ, suy nghĩ trước mắt của tôi là ném nó lại cho anh ta và bảo anh ta thay đổi nó. Nhưng sau đó tôi nghĩ về nó và không thể tìm ra lý do chính đáng để anh ta không sử dụng nó (anh ta đã sử dụng một công cụ loại chữ viết hoa để tạo db, nếu bạn đang thắc mắc).

Tôi đang nghiên cứu về chủ đề varchar(max)sử dụng và tôi thực sự không thể nghĩ ra bất kỳ lý do chính đáng nào để anh ấy không sử dụng nó.

Anh ấy không sử dụng các cột cho các chỉ mục, ứng dụng nằm trên db có giới hạn về đầu vào, vì vậy nó sẽ không cho phép các mục nhập lớn trong các trường.

Bất kỳ sự giúp đỡ sẽ được đánh giá cao để giúp tôi làm cho anh ta nhìn thấy ánh sáng :).


1
Xem câu trả lời này vì một lý do khác stackoverflow.com/questions/2009694/…
Martin Smith

Nó thật thú vị! tiếc là tôi đã không tìm thấy điều này sớm hơn. cảm ơn!
AtaLoss

5
Đối với một: bạn không thể đặt một chỉ số trên VARCHAR(MAX)cột ... mà mình làm cho tôi sử dụng nó chỉ khi thật cần thiết ....
marc_s

1
Tôi sẽ chỉ ra rằng mong đợi ứng dụng luôn kiểm soát đầu vào là điều ngu ngốc. Dữ liệu gần như sẽ tồn tại lâu hơn ứng dụng và phiên bản tiếp theo của ứng dụng có thể không có giới hạn chính xác.
HLGEM

Câu trả lời:


35

Câu trả lời của tôi cho điều này, không phải về việc sử dụng Max, mà là về lý do của VARCHAR (max) so với TEXT.

Trong cuốn sách của tôi; trước hết, Trừ khi bạn có thể hoàn toàn chắc chắn rằng bạn sẽ không bao giờ mã hóa bất cứ thứ gì ngoài văn bản tiếng Anh và mọi người sẽ không đề cập đến tên của các địa điểm nước ngoài, khi đó bạn nên sử dụng NVARCHAR hoặc NTEXT.

Thứ hai, đó là những gì các trường cho phép bạn làm.

TEXT khó cập nhật so với VARCHAR, nhưng bạn có được lợi thế của Lập chỉ mục toàn văn bản và rất nhiều điều thông minh.

Mặt khác, VARCHAR (MAX) có một số không rõ ràng, nếu kích thước của ô <8000 ký tự, nó sẽ được coi là dữ liệu Hàng. Nếu nó lớn hơn, nó sẽ được coi là LOB cho mục đích lưu trữ. Bởi vì bạn không thể biết điều này nếu không truy vấn RBAR, điều này có thể có các chiến lược tối ưu hóa cho những nơi mà bạn cần chắc chắn về dữ liệu của mình và chi phí cho bao nhiêu lần đọc.

Mặt khác, nếu việc sử dụng của bạn tương đối nhàm chán và bạn không mong đợi gặp vấn đề với kích thước dữ liệu (IE bạn đang sử dụng .Net và do đó không phải lo lắng về kích thước của các đối tượng string / char * của bạn) thì sử dụng VARCHAR (max) là ổn.


4
một điều tôi nhận thấy khi đọc các bài báo về nó, đó là khi bạn truy vấn một bảng, nó phải đệm kích thước tối đa của một bản ghi trong bộ nhớ. do đó có thể là một vấn đề, nhưng trong môi trường hiện nay với nhiều hợp đồng biểu diễn (nếu không phải là terabyte) và với ram rẻ và dễ nâng cấp, nó giảm đáng kể vấn đề này xuống còn gì.
AtaLoss

14
Câu trả lời này dường như ngụ ý rằng chỉ có thể sử dụng lập chỉ mục toàn văn với textkiểu dữ liệu. Đây không phải là trường hợp. textlà kiểu dữ liệu không được dùng nữa và không có lợi thế hơn varchar(max)AFAIK.
Martin Smith

7
Một lý do khác để không sử dụng TEXT / NTEXT là chúng không được dùng nữa.
Aaron Bertrand

1
Bạn có thể trích dẫn điều đó? Tôi chỉ biết rằng TEXT IN ROW không được dùng nữa.
Russ Clarke

1
MSSQL Books Online : Các kiểu dữ liệu ntext, văn bản và hình ảnh sẽ bị xóa trong phiên bản tương lai của Microsoft SQL Server. Tránh sử dụng các loại dữ liệu này trong công việc phát triển mới và lên kế hoạch sửa đổi các ứng dụng hiện đang sử dụng chúng. Thay vào đó, hãy sử dụng nvarchar (tối đa), varchar (tối đa) và varbinary (tối đa).
tibx

12

Có một bài đăng trên blog về lý do tại sao không sử dụng varchar max ở đây

Biên tập

Sự khác biệt cơ bản là nơi dữ liệu được lưu trữ. Hàng Dữ liệu SQL có kích thước tối đa là 8000 byte (hoặc là 8K). Sau đó, một varchar 2GB (tối đa) không thể được lưu trữ trong hàng dữ liệu. SQL Server lưu trữ nó "Hết hàng".

Do đó, bạn có thể nhận được một lần truy cập hiệu suất vì dữ liệu sẽ không ở cùng một vị trí trên đĩa, hãy xem: http://msdn.microsoft.com/en-us/library/ms189087.aspx


1
Vâng, tôi đã đọc nó, nhưng nó vẫn để lại cho tôi những câu hỏi. Nếu mã được mã hóa chính xác, để dữ liệu bị giới hạn trong ứng dụng, thì nó sẽ không bị suy giảm hiệu suất. Lập chỉ mục không phải là một vấn đề, và điểm cuối cùng là về thiết kế, điều mà bạn tôi không quan tâm.
AtaLoss

1
varchar (max) sẽ không được lưu trữ ngoài hàng trừ khi dữ liệu được lưu trữ trong hàng vượt quá giới hạn của hàng (vâng, là khoảng 8k). Tức là nếu bạn có văn bản "hello world" được lưu trữ trong varchar max trong bảng có 3 cột, rất có thể nó sẽ không được lưu trữ ngoài hàng.
AtaLoss

Lý do không sử dụng chúng là chúng không thể được lập chỉ mục. Việc sử dụng các ứng dụng nvarchar (max) hoặc varchar (max) mà bạn mong muốn có dữ liệu cần nó là một việc làm kém.
HLGEM

Nó không phải lúc nào cũng thành công. Quá trình quét bảng sẽ tăng tốc nếu kích thước hàng giảm. Nếu varchar (max) được đề cập hiếm khi được sử dụng trong các truy vấn, việc di chuyển nó ra khỏi hàng sẽ làm tăng hiệu suất.
johnnycrash

2
Lần truy cập hiệu suất có giá trị tính chính xác trong hoạt động khi bạn không thể đoán trước kích thước của một chuỗi mà bạn có thể cần chèn vào một hàng.
binki

2

Nếu bạn đang làm việc trong môi trường OLTP, bạn quan tâm đến hiệu suất. Từ các mối quan tâm về chi phí và điều chỉnh đến các giới hạn lập chỉ mục và tắc nghẽn truy vấn. Việc sử dụng varcahr (max) hoặc bất kỳ loại LOB nào khác rất có thể sẽ trái với hầu hết các phương pháp hay nhất về thiết kế, vì vậy, trừ khi có một nhu cầu kinh doanh cụ thể không thể xử lý thông qua việc sử dụng một số cơ chế nhập khác và chỉ một varchar (max) mới phù hợp với Vậy thì tại sao lại đặt hệ thống và ứng dụng của bạn vào loại vấn đề về chi phí và hiệu suất vốn có trong một trong các kiểu dữ liệu LOB?

Mặt khác, nếu bạn đang làm việc trong môi trường OLAP hoặc trong môi trường Star Schema DW với bảng Thứ nguyên có các trường mô tả tự nhiên cần dài dòng thì đó là một varchar (tối đa), miễn là bạn không thêm nó vào chỉ mục, có thể có ích đấy. Tuy nhiên, tôi vẫn khuyên bạn nên sử dụng một char (x) varchar (x) Vì cách tốt nhất là chỉ sử dụng những tài nguyên mà bạn nhất thiết phải có để hoàn thành công việc.


1

KHÔNG nên sử dụng chúng trừ khi bạn mong đợi một lượng lớn dữ liệu và đây là lý do tại sao (trực tiếp từ Sách Trực tuyến):

Không thể chỉ định các cột thuộc kiểu dữ liệu đối tượng lớn (LOB) ntext, text, varchar (max), nvarchar (max), varbinary (max), xml hoặc image làm cột chính cho một chỉ mục.

Nếu bạn muốn giảm hiệu suất, hãy sử dụng nvarchar cho mọi thứ.


2
Nhưng nếu bạn không bao giờ gõ vào cột đó ngay từ đầu thì sao? Nếu bạn đang lưu trữ một khối văn bản, có thể bạn đang tìm kiếm nó bằng một cột khóa khác. Mối quan tâm lớn này là gì về việc cần đặt các chỉ mục trên các cột có khả năng sẽ lưu trữ văn bản dạng tự do và không bao giờ xuất hiện trong WHEREngoại trừ có thể để kiểm tra IS NULL?
binki

@binki, lời khuyên là không nên sử dụng varchar (max) cho mọi thứ vì sẽ có những trường bạn cần lập chỉ mục. Nó chỉ dành cho khi bạn cần một lượng lớn dữ liệu.
HLGEM

1
Chỉ vì nó từ một cuốn sách trực tuyến không có nghĩa là nó đúng :) Một ví dụ khác về việc đôi khi sử dụng đúng (MAX) là khi bạn đang lưu trữ các chuỗi từ một nguồn (ví dụ: các đốm màu, trường NOSQL) chưa được kích thước, vì vậy bạn không nên ' t biết nó có thể lớn như thế nào. Và tôi đồng ý với @binki, thường có những cột mà bạn biết rằng bạn sẽ không bao giờ lập chỉ mục.
8forty

1

Redgate đã viết một bài báo tuyệt vời về điều này.
https://www.red-gate.com/simple-talk/sql/database-administration/whats-the-point-of-using-varcharn-anymore/

Kết luận

  • Khi thích hợp, hãy sử dụng VARCHAR (n) thay vì VARCHAR (MAX) vì lý do thiết kế tốt nếu không mang lại lợi ích về hiệu suất và vì dữ liệu VARCHAR (MAX) không nén
  • Lưu trữ chuỗi lớn mất nhiều thời gian hơn lưu trữ chuỗi nhỏ.
  • Việc cập nhật giá trị VARCHAR (MAX) trong hàng từ dưới 8.000 đến hơn 8.000 sẽ tương đối chậm, nhưng sự khác biệt cho một giao dịch có thể sẽ không thể đo lường được.
  • Việc cập nhật giá trị VARCHAR (MAX) trong hàng từ hơn 8.000 đến dưới 8.000 sẽ nhanh hơn so với khi bảng được đặt để lưu trữ dữ liệu ngoài hàng.
  • Sử dụng tùy chọn out-of-row cho VARCHAR (MAX) sẽ gây ra quá trình ghi chậm hơn cho đến khi các chuỗi rất dài.

0

Tôi không biết máy chủ sql xử lý các trường varchar lớn (đã khai báo) như thế nào từ góc độ hiệu suất, bộ nhớ và lưu trữ .. nhưng giả sử nó hoạt động hiệu quả như các trường varchar được khai báo nhỏ hơn, thì vẫn có lợi ích của các ràng buộc toàn vẹn.

Ứng dụng nằm trên db được cho là có giới hạn đối với đầu vào, nhưng cơ sở dữ liệu có thể báo lỗi đúng cách nếu ứng dụng có lỗi về mặt này.


Đây là một điểm tốt, đặc biệt nếu bạn không sử dụng ngôn ngữ được quản lý để đọc các chuỗi của mình.
Russ Clarke

Đó là một điểm tốt. Tôi sẽ đề cập đến vấn đề này, nó đang được phát triển trong c # 3.5 hoặc 4 (tôi tin rằng, tôi nên hỏi anh ấy).
AtaLoss


@RussClarke Các chuỗi có độ dài thay đổi có thực sự là một thứ chỉ được quản lý không? Có vẻ như bạn chưa bao giờ gặp phải phân bổ đống trong môi trường không được quản lý :-p.
binki

@MartinSmith Đó là những cải tiến hiệu suất rất nhỏ. Ngoài ra, blogger đang sử dụng VARCHAR(MAX)với các so sánh và trong WHEREmệnh đề. Trường hợp sử dụng mà tôi mong đợi VARCHAR(MAX)là thứ gì đó mà bạn sẽ không so sánh hoặc WHEREtrong SQL — ví dụ: một blog nội dung bài đăng trên blog, một mô tả văn bản dạng tự do về một thứ gì đó. Nếu bạn muốn so sánh hoặc WHERE, thì tất nhiên ràng buộc sẽ hữu ích. Ví dụ của anh ấy 'abc'thậm chí có thể được dịch thành một so sánh của hai số nguyên. Đó không phải là loại dữ liệu một puts trong một VARCHAR(MAX)...
binki

0

Sự khác biệt nằm ở chỗ tiếp theo:
VARCHAR(X)có thể được lập chỉ mục và lưu trữ trong MDF/NDFtệp dữ liệu.
VARCHAR(MAX)không thể được lập chỉ mục vì có thể đạt đến khối lượng lớn và sau đó sẽ được lưu trữ dưới dạng tệp riêng biệt chứ không phải trong MDF/NDFtệp dữ liệu.


6
Chính xác thì bạn nghĩ MS SQL đang lưu trữ dữ liệu LOB ở đâu, nếu không phải trong các tệp .mdf?

0

   Hơi lỗi thời khi tin rằng ứng dụng sẽ chỉ chuyển các chuỗi ngắn vào cơ sở dữ liệu và điều đó sẽ ổn thôi .

   Trong thời hiện đại, bạn dự đoán rằng cơ sở dữ liệu sẽ được truy cập chủ yếu bởi ứng dụng hiện tại, nhưng có thể có một phiên bản ứng dụng trong tương lai, (nhà phát triển của phiên bản đó có biết giữ các chuỗi dưới một độ dài nhất định không?)

   Bạn PHẢI dự đoán rằng các dịch vụ web, quy trình ETL, LYNC to SQL và bất kỳ số lượng công nghệ đã có và / hoặc chưa tồn tại nào khác sẽ được sử dụng để truy cập cơ sở dữ liệu của bạn.

   Nói chung, tôi cố gắng không vượt quá varchar (4000), vì xét cho cùng thì đó là bốn nghìn ký tự . Nếu tôi vượt quá mức đó, thì tôi tìm đến các kiểu dữ liệu khác để lưu trữ bất cứ thứ gì mà tôi đang cố gắng lưu trữ. Brent Ozar đã viết một số thứ khá hay về điều này.

   Tất cả những gì đã nói, điều quan trọng là phải đánh giá cách tiếp cận của thiết kế hiện tại đối với các yêu cầu hiện tại của bạn khi bạn đang thực hiện một dự án. Có ý tưởng về cách hoạt động của các bộ phận khác nhau, hiểu sự đánh đổi của các phương pháp tiếp cận khác nhau và giải quyết vấn đề trong tầm tay. Thực hiện một số tiên đề tuyệt vời có thể dẫn đến sự tuân thủ một cách mù quáng và có thể biến bạn thành một kẻ mê muội .

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.