Có bất kỳ nhược điểm nào khi luôn sử dụng nvarchar (MAX) không?


342

Trong SQL Server 2005, có bất kỳ nhược điểm nào khi tạo tất cả các trường ký tự nvarchar (MAX) thay vì chỉ định độ dài một cách rõ ràng, ví dụ nvarchar (255) không? (Ngoài một điều hiển nhiên là bạn không thể giới hạn độ dài trường ở cấp cơ sở dữ liệu)


1
Tôi không hiểu tại sao bạn muốn cho ai đó nhập tên của hơn 8000 ký tự.
DForck42

2
Logic tương tự có thể được áp dụng cho các ngôn ngữ lập trình. Tại sao không quay lại biến thể VB6 cũ cho tất cả dữ liệu của chúng tôi? Tôi không nghĩ rằng có séc và số dư ở nhiều nơi nhất thiết là xấu.
Matt Spradley


10
Cập nhật của bạn nên là câu trả lời của riêng nó cho câu hỏi này.
Johann

câu trả lời trong câu hỏi chuyển sang câu trả lời thích hợp khi tác giả ban đầu chưa thực hiện nó. stackoverflow.com/a353177895/10245 Tôi hình 7 năm là đủ thời gian :-)
Tim Abell

Câu trả lời:


153

Câu hỏi tương tự đã được hỏi trên Diễn đàn MSDN:

Từ bài viết gốc (nhiều thông tin hơn ở đó):

Khi bạn lưu trữ dữ liệu vào cột VARCHAR (N), các giá trị được lưu trữ theo cách vật lý theo cùng một cách. Nhưng khi bạn lưu trữ nó vào cột VARCHAR (MAX), phía sau màn hình, dữ liệu được xử lý dưới dạng giá trị văn bản. Vì vậy, có một số xử lý bổ sung cần thiết khi xử lý giá trị VARCHAR (MAX). (chỉ khi kích thước vượt quá 8000)

VARCHAR (MAX) hoặc NVARCHAR (MAX) được coi là "loại giá trị lớn". Các loại giá trị lớn thường được lưu trữ 'ngoài hàng'. Điều đó có nghĩa là hàng dữ liệu sẽ có một con trỏ đến một vị trí khác nơi 'giá trị lớn' được lưu trữ ...


2
Vì vậy, câu hỏi nên là, có sự khác biệt giữa việc sử dụng N / VARCHAR (MAX) và N / TEXT không?
Unsliced

18
Nếu tôi nhớ lại chính xác, không phải họ chỉ được lưu trữ ngoài hàng nếu kích thước vượt quá 8k sao?
Sam Schutte

79
Tôi đọc câu trả lời là "không, không có bất lợi nào khi sử dụng N/VARCHAR(MAX)" bởi vì có xử lý bổ sung "chỉ khi kích thước vượt quá 8000". Do đó, bạn chỉ chịu chi phí khi cần thiết và cơ sở dữ liệu của bạn ít hạn chế hơn . Tôi đang đọc sai à? Có vẻ như bạn hầu như luôn muốn N/VARCHAR(MAX)hơn là N/VARCHAR(1-8000)...
Kent Boogaart

1
Liên kết chết ở trên - liên kết hoạt động cho câu hỏi trên MSDN là social.msdn.microsoft.com/Forums/en-US/sqlgetstarted/thread/iêu
Jagd

68
Thật không may câu trả lời này có một số vấn đề. Nó làm cho ranh giới 8k có vẻ như là một con số kỳ diệu, không đúng, giá trị bị đẩy ra khỏi hàng dựa trên nhiều yếu tố, bao gồm sp_tableoptions: msdn.microsoft.com/en-us/l Library / ms173530.aspx . Các loại VARCHAR (255) cũng có thể bị đẩy ra khỏi hàng, 'chi phí' được đề cập có thể giống hệt nhau cho MAX và 255. Nó so sánh các loại MAX với các loại văn bản, khi chúng khác biệt (API hoàn toàn khác nhau để thao tác, lưu trữ khác nhau vv). Không đề cập đến sự khác biệt thực tế: không có chỉ mục, không có hoạt động trực tuyến trên các loại MAX
Remus Rusanu

50

Đó là một câu hỏi công bằng và anh ấy đã nói rõ hơn

Nhược điểm có thể bao gồm:

Ý nghĩa về hiệu suất Trình tối ưu hóa truy vấn sử dụng kích thước trường để xác định kế hoạch thực hiện hiệu quả nhất

"1. Phân bổ không gian trong phần mở rộng và các trang của cơ sở dữ liệu rất linh hoạt. Do đó, khi thêm thông tin vào trường bằng cập nhật, cơ sở dữ liệu của bạn sẽ phải tạo một con trỏ nếu dữ liệu mới dài hơn dữ liệu được chèn trước đó. trở nên bị phân mảnh = hiệu suất thấp hơn trong hầu hết mọi thứ, từ chỉ mục đến xóa, cập nhật và chèn. " http://sqlblogcasts.com/bloss/simons/archive/2006/02/11/Why-use-anything-but-varchar_2800_max_2900_.aspx

Ý nghĩa tích hợp - khó cho các hệ thống khác biết cách tích hợp với cơ sở dữ liệu của bạn Sự tăng trưởng dữ liệu không thể đoán trước Các sự cố bảo mật có thể xảy ra, ví dụ: bạn có thể làm sập hệ thống bằng cách chiếm hết dung lượng đĩa

Có một bài viết hay ở đây: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html


4
+1 Đối với các ý nghĩa tích hợp và bảo mật. Đây là một góc ban đầu để xem xét khi hầu hết các câu trả lời khác nói về hiệu suất. Liên quan đến ý nghĩa tích hợp, bất kỳ công cụ nào (như người viết báo cáo hoặc người thiết kế biểu mẫu) sử dụng dữ liệu meta để cung cấp kích thước điều khiển mặc định hợp lý sẽ cần nhiều công việc hơn để sử dụng nếu tất cả các cột đều được sử dụng varchar(max).
vỡ mộng

Tích hợp bởi cơ sở dữ liệu là điều vô lý nhất những gì tôi biết. Nếu nó chỉ là nhập được thực hiện một lần, bạn có thể kiểm tra dữ liệu trước bằng chức năng LEN.
Tối đa

30

Dựa trên liên kết được cung cấp trong câu trả lời được chấp nhận, có vẻ như:

  1. 100 ký tự được lưu trữ trong một nvarchar(MAX)trường sẽ được lưu trữ không khác với 100 ký tự trong một nvarchar(100)trường - dữ liệu sẽ được lưu trữ nội tuyến và bạn sẽ không có chi phí đọc và ghi dữ liệu 'ngoài luồng'. Vì vậy, không phải lo lắng ở đó.

  2. Nếu kích thước lớn hơn 4000, dữ liệu sẽ được lưu trữ tự động 'ngoài hàng', đó là những gì bạn muốn. Vì vậy, không có lo lắng ở đó.

Tuy nhiên...

  1. Bạn không thể tạo một chỉ mục trên một nvarchar(MAX)cột. Bạn có thể sử dụng lập chỉ mục toàn văn bản, nhưng bạn không thể tạo một chỉ mục trên cột để cải thiện hiệu suất truy vấn. Đối với tôi, điều này niêm phong thỏa thuận ... đó là một bất lợi nhất định khi luôn sử dụng nvarchar (MAX).

Phần kết luận:

Nếu bạn muốn một loại "độ dài chuỗi phổ quát" trong toàn bộ cơ sở dữ liệu của bạn, có thể được lập chỉ mục và sẽ không lãng phí không gian và thời gian truy cập, thì bạn có thể sử dụng nvarchar(4000).


1
fyi đây là một chỉnh sửa được thêm vào câu hỏi ban đầu nên được đăng dưới dạng câu trả lời
Tim Abell

1
Cảm ơn, cho tôi đây là câu trả lời cuối cùng. Tôi đã tự hỏi mình như vậy - tại sao không sử dụng nvarchar(max)tất cả thời gian - như stringtrong C #? - nhưng điểm 3) (vấn đề chỉ số) đang đưa ra câu trả lời.
Cảnh sát SQL

1
Đã thêm một chỉnh sửa. Là một loại "độ dài chuỗi phổ quát", bạn luôn có thể sử dụngnvarchar(4000)
SQL Police

@QueryGeorge Xem câu trả lời xuất sắc này của Martin Smith về tác động đối với hiệu suất truy vấn của việc khai báo các cột rộng hơn bao giờ hết
billinkc 13/03/2016

@billinkc Cảm ơn, đó là một bài viết tuyệt vời. OK, vì vậy kích thước thực sự ảnh hưởng đến perfromance. Tôi sẽ chỉnh sửa câu trả lời một lần nữa.
Cảnh sát SQL

28

Đôi khi bạn muốn kiểu dữ liệu thực thi một số ý nghĩa đối với dữ liệu trong đó.

Ví dụ: bạn có một cột thực sự không nên dài hơn 20 ký tự. Nếu bạn xác định cột đó là VARCHAR (MAX), một số ứng dụng giả mạo có thể chèn một chuỗi dài vào đó và bạn sẽ không bao giờ biết hoặc có bất kỳ cách nào để ngăn chặn nó.

Lần tiếp theo ứng dụng của bạn sử dụng chuỗi đó, với giả định rằng độ dài của chuỗi là khiêm tốn và hợp lý cho tên miền mà nó đại diện, bạn sẽ gặp một kết quả không thể đoán trước và khó hiểu.


9
Tôi đồng ý với điều này và một số ý kiến ​​khác, nhưng tôi vẫn cho rằng đây là trách nhiệm của tầng lớp doanh nghiệp. Vào thời điểm nó đạt đến tầng cơ sở dữ liệu, nó sẽ nhanh chóng chào và lưu trữ giá trị, bất kể nó dài đến mức nào. Tôi nghĩ những gì thực sự chơi ở đây là tôi nghĩ khoảng 90% thời gian khi một nhà phát triển chỉ định varchar (255), ý định của anh ta không thực sự là 255 ký tự, nhưng một số giá trị độ dài không xác định. Và đưa ra sự đánh đổi giữa các giá trị lớn bất hợp lý trong db của tôi và các ngoại lệ không lường trước được, tôi sẽ lấy các giá trị lớn.
Chris B. BehDR

4
Nếu họ chỉ định VARCHAR (255) để chỉ ra một số độ dài không xác định thì đó là lỗi của họ vì đã không nghiên cứu chính xác những gì họ đang thiết kế. Giải pháp là để nhà phát triển thực hiện công việc của họ, không phải cho cơ sở dữ liệu để cho phép các giá trị không hợp lý.
Tom H

10
không hữu ích cho tác giả. ông loại trừ rõ ràng câu hỏi này mà bạn đã đưa ra câu trả lời.
usr

6
@ Chris B BehDR: Tôi không đồng ý; lược đồ cơ sở dữ liệu một phần của logic nghiệp vụ. Sự lựa chọn các bảng, quan hệ, trường và loại dữ liệu là tất cả logic nghiệp vụ - và đáng để sử dụng RDBMS để thực thi các quy tắc của logic nghiệp vụ này. Vì một lý do, rất hiếm khi chỉ có một tầng ứng dụng truy cập cơ sở dữ liệu; ví dụ: bạn có thể có các công cụ nhập và trích xuất dữ liệu bỏ qua tầng kinh doanh chính, điều đó có nghĩa là bạn thực sự cần DB để thực thi các quy tắc.
Vince Bowdren

1
Nếu bạn không cần hoặc thực sự muốn các chuỗi dài được lưu trữ, thì tốt hơn là thực thi ý nghĩa trên dữ liệu. Ví dụ: nếu lưu trữ trường PostCode, bạn có cho phép ai đó nhập hàng trăm hoặc hàng nghìn ký tự khi tối đa là 10 say.- kích thước tối đa phải được xác thực ở tất cả các cấp, ứng dụng khách, tầng doanh nghiệp VÀ cơ sở dữ liệu. Nếu sử dụng cách tiếp cận Model First, chẳng hạn như với C # và Entity Framework, bạn có thể xác định mức tối đa hóa của mình tại mô hình và áp dụng nó cho cơ sở dữ liệu, logic nghiệp vụ và xác thực ứng dụng khách (với xác thực jquery). Chỉ sử dụng nvarchar (tối đa) nếu thực sự cần thiết
Peter Kerr

21

Tôi đã kiểm tra một số bài viết và tìm tập lệnh kiểm tra hữu ích từ đây: http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx Sau đó thay đổi nó để so sánh giữa NVARCHAR (10) so với NVARCHAR (4000) so với NVARCHAR (MAX) ) và tôi không tìm thấy sự khác biệt về tốc độ khi sử dụng các số được chỉ định nhưng khi sử dụng MAX. Bạn có thể tự kiểm tra. Hy vọng điều này giúp đỡ.

SET NOCOUNT ON;

--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
        @StartTime DATETIME;
--=====         
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO

4
Nó thật thú vị. Trên hộp của tôi, có vẻ như chiếc MAX chậm hơn gấp 4 lần.
stucampbell

4
Kết quả mới trên SQL Server 2012: 10 chậm hơn hai lần so với 4k và MAX chậm hơn 5,5 lần so với 4k.
cassandrad

1
Phần lớn thời gian là các diễn viên ngầm định từ varchar đến nvarchar (max). Hãy thử cái này: DECLARE \ @SomeString NVARCHAR (MAX), \ @abc NVARCHAR (max) = N'ABC ', \ @StartTime DATETIME; CHỌN @startTime = GETDATE (); CHỌN 1000000 \ @SomeString = \ @abc TỪ master.sys.all_columns ac1, master.sys.all_columns ac2; CHỌN testTime = 'MAX', Thời lượng = DATEDIFF (ms, \ @ StartTime, GETDATE ()); Phải chèn \ trước các biến để đưa nó vào bài.
Kvasi

4
Máy chủ SQL 2014 trên SSD: 150, 156, 716 (10, 4000, MAX).
Tối đa

2
Cảm ơn đã thêm một số con số thực vào cuộc thảo luận này. Chúng ta thường quên rằng xây dựng một trường hợp thử nghiệm là cách nhanh nhất để hiểu sâu hơn.
David C

13

Hãy nghĩ về nó như chỉ là một mức độ an toàn. Bạn có thể thiết kế bảng của mình mà không cần các mối quan hệ khóa ngoài - hoàn toàn hợp lệ - và đảm bảo sự tồn tại của các thực thể liên quan hoàn toàn trên lớp doanh nghiệp. Tuy nhiên, khóa ngoại được coi là thực hành thiết kế tốt vì chúng thêm một mức ràng buộc khác trong trường hợp có gì đó gây rối trên lớp nghiệp vụ. Tương tự như vậy đối với giới hạn kích thước trường và không sử dụng varchar MAX.


8

Một lý do KHÔNG nên sử dụng các trường tối đa hoặc văn bản là bạn không thể thực hiện việc xây dựng lại chỉ mục trực tuyến tức là REBUILD VỚI ONLINE = ON ngay cả với SQL Server Enterprise Edition.


1
Hạn chế tương tự này được áp dụng cho loại trường TEXT, vì vậy bạn vẫn nên sử dụng VARCHAR (MAX) thay vì TEXT.
Sẽ cạo râu

chúng tôi không thể xây dựng lại chỉ số cụm của chúng tôi do điều này. nó tiêu tốn của chúng tôi nhiều dung lượng đĩa cho đến khi chúng tôi có thể trích xuất cột vào bảng riêng của mình (chúng tôi không thể đủ khả năng khóa bảng trong hơn 7 giây)
Choco Smith

4

Vấn đề duy nhất tôi tìm thấy là chúng tôi phát triển các ứng dụng của mình trên SQL Server 2005 và trong một trường hợp, chúng tôi phải hỗ trợ SQL Server 2000. Tôi mới biết, cách khó mà SQL Server 2000 không thích tùy chọn MAX cho varchar hoặc nvarchar.


2
Vậy tại sao không chỉ phát triển trên mẫu số chung thấp nhất?
binki

4

Ý tưởng tồi khi bạn biết trường sẽ nằm trong một phạm vi được đặt - ví dụ 5 đến 10 ký tự. Tôi nghĩ tôi chỉ sử dụng tối đa nếu tôi không chắc chiều dài sẽ là bao nhiêu. Ví dụ, một số điện thoại sẽ không bao giờ nhiều hơn một số ký tự nhất định.

Bạn có thể thành thật nói rằng bạn không chắc chắn về các yêu cầu về độ dài gần đúng cho mọi trường trong bảng của bạn?

Tôi thực sự hiểu ý của bạn - có một số lĩnh vực tôi chắc chắn sẽ xem xét sử dụng varchar (max).

Điều thú vị là các tài liệu MSDN tổng hợp khá tốt:

Sử dụng varchar khi kích thước của các mục dữ liệu cột thay đổi đáng kể. Sử dụng varchar (max) khi kích thước của các mục nhập dữ liệu cột thay đổi đáng kể và kích thước có thể vượt quá 8.000 byte.

một cuộc thảo luận thú vị về vấn đề ở đây .


2
Đối với những thứ như số điện thoại, tôi sẽ dễ sử dụng trường char hơn thay vì varchar. Miễn là bạn đang duy trì một tiêu chuẩn trong bộ lưu trữ của mình và bạn không phải lo lắng về các số điện thoại từ các quốc gia khác nhau, bạn không bao giờ cần một trường biến cho một cái gì đó như số điện thoại (10 mà không có bất kỳ định dạng nào) hoặc mã zip (5 hoặc 9-10 nếu bạn thêm bốn chữ số cuối), v.v.
TheTXI

Tôi đã đề cập đến các số điện thoại có thể thay đổi chiều dài. Có lẽ tôi nên đặt điều này trong câu trả lời. Bất cứ điều gì có độ dài cố định tôi sẽ sử dụng một trường char.
RichardOD

Hoặc có lẽ tôi nên nói trong bình luận của tôi nchar hoặc char. :-)
RichardOD

2
Số lượng ký tự trong một số điện thoại là khá nhiều yêu cầu kinh doanh. Nếu bạn được yêu cầu lưu trữ mã tiêu chuẩn quốc tế cùng với số, nó có thể nhiều hơn 10. Hoặc, một số nơi trên thế giới có thể có hơn 10 chữ số cho một số điện thoại. Hãy tưởng tượng trường hợp chuyển đổi IPV4 sang IPV6. Không ai có thể tranh luận rằng chúng tôi cần nhiều hơn 12 chữ số trong những ngày IPV4 cũ. Nó có thể không tốt nếu IPV6 trở nên phổ biến. Đây lại là một thay đổi quy tắc kinh doanh trong một khoảng thời gian. Như đã nói, thay đổi là điều duy nhất chúng ta có thể mong đợi :)
bút chì

2
Hãy cẩn thận về việc giả sử bạn biết có bao nhiêu ký tự trong trường số điện thoại hoặc chúng sẽ là loại ký tự nào. Trừ khi hệ thống sử dụng dữ liệu đó để thực sự quay ra (trong trường hợp bạn phải nghiêm ngặt về các định dạng), thì người dùng có thể đặt các chuỗi dài bất ngờ ở đó, ví dụ: "0123 456 78910 yêu cầu nhận phần mở rộng 45 và sau đó chuyển sang James".
Vince Bowdren

4

Công việc của cơ sở dữ liệu là lưu trữ dữ liệu để doanh nghiệp có thể sử dụng. Một phần của việc làm cho dữ liệu đó hữu ích là đảm bảo rằng nó có ý nghĩa. Cho phép ai đó nhập số lượng ký tự không giới hạn cho tên của họ không đảm bảo dữ liệu có ý nghĩa.

Xây dựng các ràng buộc này vào lớp nghiệp vụ là một ý tưởng tốt, nhưng điều đó không đảm bảo rằng cơ sở dữ liệu sẽ vẫn còn nguyên vẹn. Cách duy nhất để đảm bảo rằng các quy tắc dữ liệu không bị vi phạm là thực thi chúng ở mức thấp nhất có thể trong cơ sở dữ liệu.


6
IMO, giới hạn độ dài dữ liệu hoàn toàn dựa trên các quy tắc kinh doanh, có thể thay đổi trong một khoảng thời gian, khi ứng dụng phát triển. Thay đổi quy tắc kinh doanh ở logic nghiệp vụ dễ dàng hơn ở cấp db. Vì vậy, tôi nghĩ rằng db phải đủ linh hoạt và không nên bị ràng buộc với các quy tắc kinh doanh, chẳng hạn như độ dài cho phép của tên, điều này phụ thuộc rất nhiều vào phần của thế giới nơi người dùng của bạn sống.
bút chì

3

Một vấn đề là nếu bạn phải làm việc với nhiều phiên bản SQL Server, MAX sẽ không luôn hoạt động. Vì vậy, nếu bạn đang làm việc với DB kế thừa hoặc bất kỳ tình huống nào khác liên quan đến nhiều phiên bản, tốt nhất bạn nên cẩn thận.


Tôi nghĩ rằng giả định bất thành văn của OP là anh ta đang xử lý hoàn toàn với các phiên bản 2005+ và các ứng dụng của anh ta sẽ không cần phải hoạt động trên các phiên bản 2000 (hoặc, ack, thấp hơn). Tôi hoàn toàn đồng ý với bạn nếu có nhu cầu hỗ trợ các phiên bản cũ hơn!
John Rudy

John Rudy: Tôi sẽ tưởng tượng đó là trường hợp, tôi chỉ biết rằng bản thân tôi đã gặp phải những trở ngại đó khi tôi không nghĩ mình sẽ đi.
TheTXI

Trên thực tế đây là một vấn đề phổ biến vẫn còn với các công cụ hiện đại do SQL CE 4 không hỗ trợ các loại cột MAX nên khả năng tương tác là một rắc rối.
JohnC

3

Như đã chỉ ra ở trên, nó chủ yếu là sự đánh đổi giữa lưu trữ và hiệu suất. Ít nhất trong hầu hết các trường hợp.

Tuy nhiên, có ít nhất một yếu tố khác cần được xem xét khi chọn n / varchar (Max) trên n / varchar (n). Là dữ liệu sẽ được lập chỉ mục (chẳng hạn như, tên cuối cùng)? Vì định nghĩa MAX được coi là LOB, nên mọi thứ được định nghĩa là MAX đều không có sẵn để lập chỉ mục. và không có chỉ mục, bất kỳ tra cứu nào liên quan đến dữ liệu như vị ngữ trong mệnh đề WHERE sẽ bị buộc phải quét toàn bộ Bảng, đây là hiệu suất tồi tệ nhất bạn có thể nhận được khi tra cứu dữ liệu.


2

1) Máy chủ SQL sẽ phải sử dụng nhiều tài nguyên hơn (bộ nhớ được phân bổ và thời gian cpu) khi xử lý nvarchar (max) so với nvarchar (n) trong đó n là một số cụ thể cho trường.

2) Điều này có nghĩa gì đối với hiệu suất?

Trên SQL Server 2005, tôi đã truy vấn 13.000 hàng dữ liệu từ một bảng có 15 cột nvarchar (tối đa). Tôi đã hẹn giờ các truy vấn nhiều lần và sau đó thay đổi các cột thành nvarchar (255) hoặc ít hơn.

Các truy vấn trước khi tối ưu hóa trung bình ở mức 2.0858 giây. Các truy vấn sau khi thay đổi trả về trung bình 1,90 giây. Đó là khoảng 184 mili giây cải tiến cho truy vấn select * cơ bản. Đó là một cải tiến 8,8%.

3) Kết quả của tôi là đồng tình với một vài bài báo khác chỉ ra rằng có sự khác biệt về hiệu suất. Tùy thuộc vào cơ sở dữ liệu của bạn và truy vấn, tỷ lệ phần trăm cải thiện có thể khác nhau. Nếu bạn không có nhiều người dùng đồng thời hoặc rất nhiều hồ sơ, thì sự khác biệt về hiệu suất sẽ không phải là vấn đề đối với bạn. Tuy nhiên, sự khác biệt hiệu suất sẽ tăng lên khi nhiều hồ sơ và người dùng đồng thời tăng lên.


1

Tôi đã có một udf mà đệm chuỗi và đặt đầu ra thành varchar (max). Nếu điều này được sử dụng trực tiếp thay vì chuyển trở lại kích thước phù hợp cho cột được điều chỉnh, hiệu suất rất kém. Cuối cùng tôi đã đặt udf đến một độ dài tùy ý bằng một ghi chú lớn thay vì dựa vào tất cả các người gọi của udf để đúc lại chuỗi thành kích thước nhỏ hơn.


1

hỗ trợ hệ thống di sản. Nếu bạn có một hệ thống đang sử dụng dữ liệu và dự kiến ​​sẽ có độ dài nhất định thì cơ sở dữ liệu là một nơi tốt để thực thi độ dài. Điều này không lý tưởng nhưng hệ thống di sản đôi khi không lý tưởng. = P


1

Nếu tất cả các dữ liệu trong một hàng (cho tất cả các cột) sẽ không bao giờ lấy hợp lý 8000 hoặc ít hơn các ký tự thì thiết kế ở lớp dữ liệu sẽ thực thi điều này.

Công cụ cơ sở dữ liệu hiệu quả hơn nhiều khi giữ mọi thứ trong bộ nhớ blob. Càng nhỏ bạn có thể hạn chế một hàng càng tốt. Càng nhiều hàng bạn có thể nhồi nhét trong một trang càng tốt. Cơ sở dữ liệu chỉ hoạt động tốt hơn khi phải truy cập ít trang hơn.


1

Các thử nghiệm của tôi đã chỉ ra rằng có sự khác biệt khi lựa chọn.

CREATE TABLE t4000 (a NVARCHAR(4000) NULL);

CREATE TABLE tmax (a NVARCHAR(MAX) NULL);

DECLARE @abc4 NVARCHAR(4000) = N'ABC';

INSERT INTO t4000
SELECT TOP 1000000 @abc4
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

DECLARE @abc NVARCHAR(MAX) = N'ABC';

INSERT INTO tmax
SELECT TOP 1000000 @abc
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

SET STATISTICS TIME ON;
SET STATISTICS IO ON;

SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;

0

Liên kết thú vị: Tại sao nên sử dụng VARCHAR khi bạn có thể sử dụng văn bản?

Đó là về PostgreSQL và MySQL, vì vậy phân tích hiệu suất là khác nhau, nhưng logic cho "nhân chứng" vẫn giữ nguyên: Tại sao buộc bản thân phải luôn lo lắng về điều gì đó có liên quan đến một tỷ lệ nhỏ thời gian? Nếu bạn đã lưu địa chỉ email vào một biến, bạn sẽ sử dụng 'chuỗi' không phải là 'chuỗi giới hạn trong 80 ký tự'.


1
Điều đó giống như lập luận rằng bạn không nên kiểm tra các ràng buộc để đảm bảo rằng tuổi của một người không phải là số âm.
Jonathan Allen

Tôi thấy một sự khác biệt giữa tính chính xác của dữ liệu và tối ưu hóa hiệu suất.
orip

0

Nhược điểm chính tôi có thể thấy là hãy nói rằng bạn có điều này:

Cái nào cung cấp cho bạn nhiều thông tin nhất về dữ liệu cần thiết cho UI?

Điều này

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](MAX) NULL,
                [CompanyName] [nvarchar](MAX) NOT NULL,
                [FirstName] [nvarchar](MAX) NOT NULL,
                [LastName] [nvarchar](MAX) NOT NULL,
                [ADDRESS] [nvarchar](MAX) NOT NULL,
                [CITY] [nvarchar](MAX) NOT NULL,
                [County] [nvarchar](MAX) NOT NULL,
                [STATE] [nvarchar](MAX) NOT NULL,
                [ZIP] [nvarchar](MAX) NOT NULL,
                [PHONE] [nvarchar](MAX) NOT NULL,
                [COUNTRY] [nvarchar](MAX) NOT NULL,
                [NPA] [nvarchar](MAX) NULL,
                [NXX] [nvarchar](MAX) NULL,
                [XXXX] [nvarchar](MAX) NULL,
                [CurrentRecord] [nvarchar](MAX) NULL,
                [TotalCount] [nvarchar](MAX) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]

Hay cái này?

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](50) NULL,
                [CompanyName] [nvarchar](50) NOT NULL,
                [FirstName] [nvarchar](50) NOT NULL,
                [LastName] [nvarchar](50) NOT NULL,
                [ADDRESS] [nvarchar](50) NOT NULL,
                [CITY] [nvarchar](50) NOT NULL,
                [County] [nvarchar](50) NOT NULL,
                [STATE] [nvarchar](2) NOT NULL,
                [ZIP] [nvarchar](16) NOT NULL,
                [PHONE] [nvarchar](18) NOT NULL,
                [COUNTRY] [nvarchar](50) NOT NULL,
                [NPA] [nvarchar](3) NULL,
                [NXX] [nvarchar](3) NULL,
                [XXXX] [nvarchar](4) NULL,
                [CurrentRecord] [nvarchar](50) NULL,
                [TotalCount] [nvarchar](50) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]

3
Tôi thích logic kinh doanh nói với tôi rằng Tên Công ty có thể có tối đa 50 ký tự thay vì dựa vào bảng cơ sở dữ liệu cho thông tin đó.
Khan

Tôi đồng ý với Jeff. Tôi không nghĩ cửa hàng kiên trì là nơi thích hợp để xác định quy tắc kinh doanh của bạn. Và trong một kiến ​​trúc phân lớp, giao diện người dùng của bạn thậm chí sẽ không biết về lớp liên tục.
stucampbell

Tất nhiên trừ khi bạn đang sử dụng một giá trị bị ràng buộc với một kích thước cụ thể, ví dụ mã ISO cho quốc gia.
Ben

2
Điều đó có liên quan gì đến một def bảng? Bạn vẫn có thể có logic kinh doanh. Tôi nghĩ rằng quan điểm của bạn không có ý nghĩa gì liên quan đến cách một bảng được thiết kế. Nếu bạn vẫn muốn thiết kế một số loại định nghĩa trong lớp doanh nghiệp của bạn, thì hãy là nó. Mặc dù những gì sẽ có ý nghĩa hơn, dù sao cũng đang sử dụng một Proc được lưu trữ trong lớp nghiệp vụ; không phải là một bảng def ??
carlos martini

1
Nó có vẻ không phổ biến nhưng tôi đồng ý với carlos, nếu db đặt kích thước tối đa thì bạn có thể thoải mái trong tất cả các lớp bạn xây dựng trên nó, những gì bạn có khả năng phải đối phó. Điều này đặc biệt quan trọng nếu bạn có nhiều hệ thống ghi vào cơ sở dữ liệu của bạn.
Tim Abell

0

Một nhược điểm là bạn sẽ thiết kế xung quanh một biến không thể đoán trước và có thể bạn sẽ bỏ qua thay vì tận dụng cấu trúc dữ liệu SQL Server nội bộ, dần dần được tạo thành từ Row (s), Page (s) và Extent (s).

Điều này khiến tôi suy nghĩ về sự liên kết cấu trúc dữ liệu trong C và việc nhận thức được sự liên kết thường được coi là một điều tốt (TM). Ý tưởng tương tự, bối cảnh khác nhau.

Trang MSDN cho Trang và Phạm vi

Trang MSDN cho dữ liệu tràn hàng


0

Đầu tiên tôi nghĩ về điều này, nhưng sau đó lại nghĩ. Có ý nghĩa về hiệu suất, nhưng đồng thời nó cũng đóng vai trò là một dạng tài liệu để có ý tưởng về kích thước của các trường thực sự. Và nó thực thi khi cơ sở dữ liệu đó nằm trong một hệ sinh thái lớn hơn. Theo tôi, chìa khóa là được cho phép nhưng chỉ trong phạm vi lý do.

ok, đây là cảm xúc của tôi đơn giản về vấn đề kinh doanh và logic lớp dữ liệu. Điều này phụ thuộc, nếu DB của bạn là tài nguyên được chia sẻ giữa các hệ thống chia sẻ logic kinh doanh thì tất nhiên đó có vẻ là một nơi tự nhiên để thực thi logic đó, nhưng đó không phải là cách TỐT NHẤT để làm điều đó, cách TỐT NHẤT là cung cấp API, điều này cho phép sự tương tác được kiểm tra và giữ logic kinh doanh ở nơi nó thuộc về, nó giữ cho các hệ thống được tách rời, nó giữ cho các tầng của bạn trong một hệ thống được tách rời. Tuy nhiên, nếu cơ sở dữ liệu của bạn được cho là chỉ phục vụ một ứng dụng, thì hãy suy nghĩ về AGILE, điều gì là sự thật? thiết kế cho bây giờ. Nếu và khi cần truy cập như vậy, hãy cung cấp API cho dữ liệu đó.

rõ ràng, đây chỉ là lý tưởng, nếu bạn đang làm việc với một hệ thống hiện có thì khả năng là bạn sẽ cần phải làm điều đó khác đi ít nhất là trong thời gian ngắn.


-1

Điều này sẽ gây ra vấn đề về hiệu năng, mặc dù nó có thể không bao giờ gây ra bất kỳ vấn đề thực tế nào nếu cơ sở dữ liệu của bạn nhỏ. Mỗi bản ghi sẽ chiếm nhiều dung lượng hơn trên ổ cứng và cơ sở dữ liệu sẽ cần đọc thêm các phần của đĩa nếu bạn đang tìm kiếm thông qua nhiều bản ghi cùng một lúc. Ví dụ: một bản ghi nhỏ có thể vừa với 50 cho một khu vực và một bản ghi lớn có thể phù hợp với 5. Bạn cần đọc gấp 10 lần dữ liệu từ đĩa bằng cách sử dụng bản ghi lớn.


5
-1. Một chuỗi có độ dài 100 được lưu trữ trong một nvarchar(max)cột không chiếm nhiều dung lượng đĩa hơn so với khi nó nằm trong một nvarchar(100)cột.
Martin Smith

Những gì bạn mô tả là chính xác nếu kích thước của dữ liệu được lưu trữ lớn hơn, nhưng câu hỏi này là về loại dữ liệu có ý nghĩa về hiệu suất hoặc các cân nhắc khác.

-2

Nó sẽ làm cho thiết kế màn hình trở nên khó khăn hơn vì bạn sẽ không còn có thể dự đoán độ rộng của điều khiển của bạ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.