varchar (500) có lợi thế hơn so với varchar (8000)?


90

Tôi đã đọc về điều này trên các diễn đàn MSDN và ở đây và tôi vẫn chưa rõ. Tôi nghĩ điều này là chính xác: Varchar (max) sẽ được lưu trữ dưới dạng kiểu dữ liệu văn bản, vì vậy điều đó có nhược điểm. Vì vậy, giả sử trường của bạn chắc chắn sẽ có dưới 8000 ký tự. Giống như trường BusinessName trong bảng cơ sở dữ liệu của tôi. Trên thực tế, một tên doanh nghiệp có thể sẽ luôn dưới (kéo theo một con số khiến tôi không hiểu) 500 ký tự. Có vẻ như rất nhiều trường varchar mà tôi chạy qua nằm dưới số ký tự 8k.

Vì vậy, tôi có nên đặt trường đó thành varchar (500) thay vì varchar (8000) không? Từ những gì tôi hiểu về SQL, không có sự khác biệt giữa hai điều đó. Vì vậy, để làm cho cuộc sống trở nên dễ dàng, tôi muốn xác định tất cả các trường varchar của mình là varchar (8000). Điều đó có bất kỳ nhược điểm?

Liên quan: Kích thước của các cột varchar (Tôi không cảm thấy như cái này trả lời câu hỏi của tôi).


6
Hãy tưởng tượng cố gắng để phù hợp với một tên doanh nghiệp dài 500 ký tự trên danh thiếp ... :)
OMG Ngựa Non

2
@OMG Ponies: mỗi khi tôi nhìn thấy tên người dùng của bạn, tôi cười thầm. Bây giờ, bạn đã nói gì? (Đùa thôi)
jcollum

4
@jcollum: SpaceMan Spiff sẽ luôn nhận được phiếu bầu của tôi. Điều đó không đúng - bất kỳ Calvin & Hobbes nào cũng vậy, nhưng đặc biệt là những tác phẩm điêu khắc tuyết. Hay khủng long tyranosaurus bay F-14. Nhưng tôi lạc đề ...
OMG Ngựa Non

Câu trả lời:


20

Từ quan điểm xử lý, sẽ không tạo ra sự khác biệt khi sử dụng varchar (8000) so với varchar (500). Việc xác định độ dài tối đa mà một trường phải giữ và tạo cho varchar của bạn độ dài đó là một kiểu "thực hành tốt". Đó là thứ có thể được sử dụng để hỗ trợ xác thực dữ liệu. Ví dụ: đặt tên viết tắt của tiểu bang là 2 ký tự hoặc mã bưu chính / zip là 5 hoặc 9 ký tự. Điều này từng là một sự khác biệt quan trọng hơn khi dữ liệu của bạn tương tác với các hệ thống hoặc giao diện người dùng khác mà độ dài trường là rất quan trọng (ví dụ: tập dữ liệu tệp phẳng máy tính lớn), nhưng ngày nay tôi nghĩ đó là thói quen hơn bất kỳ thứ gì khác.


3
Có ý nghĩa ... đối với những thứ tự nhiên có độ dài tối đa. Nhưng bạn sẽ làm gì khi độ dài tối đa không rõ ràng? Ví dụ: tên doanh nghiệp.
jcollum

2
Đối với những thứ như vậy, nếu tôi không thấy trước bất kỳ cách nào để dự báo kích thước có thể là bao nhiêu, thì tôi thường sử dụng varchar (8000) hoặc varchar (max), tùy thuộc vào loại dữ liệu
BBlake

4
Có vẻ như điều này tạo sự khác biệt trong hoạt động, thậm chí vào năm 2017: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name

1
Câu trả lời gần đây cho thấy có những chi phí: nó ảnh hưởng đến tối ưu hóa logic câu trả lời Martin Smith và cũng xem xét tổng 8K vấn đề kích thước hàng được đề cập bởi gbnOliver .
ToolmakerSteve

124

Một ví dụ mà điều này có thể tạo ra sự khác biệt là nó có thể ngăn chặn việc tối ưu hóa hiệu suất tránh thêm thông tin lập phiên bản hàng vào bảng có sau trình kích hoạt.

Điều này được bao phủ bởi SQL Kiwi tại đây

Kích thước thực của dữ liệu được lưu trữ là không quan trọng - đó là kích thước tiềm năng mới là vấn đề quan trọng.

Tương tự, nếu sử dụng các bảng được tối ưu hóa bộ nhớ kể từ năm 2016, có thể sử dụng cột LOB hoặc kết hợp độ rộng cột có thể vượt quá giới hạn inrow nhưng bị phạt.

Các cột (Tối đa) luôn được lưu trữ ngoài hàng. Đối với các cột khác, nếu kích thước hàng dữ liệu trong định nghĩa bảng có thể vượt quá 8.060 byte, SQL Server đẩy (các) cột có độ dài thay đổi lớn nhất ra khỏi hàng. Một lần nữa, nó không phụ thuộc vào lượng dữ liệu bạn lưu trữ ở đó.

Điều này có thể có tác động tiêu cực lớn đến việc tiêu thụ và hoạt động của bộ nhớ

Một trường hợp khác mà việc khai báo quá nhiều độ rộng cột có thể tạo ra sự khác biệt lớn là nếu bảng sẽ được xử lý bằng SSIS. Bộ nhớ được cấp phát cho các cột có độ dài thay đổi (không phải BLOB) được cố định cho mỗi hàng trong cây thực thi và theo độ dài tối đa được khai báo của các cột, điều này có thể dẫn đến việc sử dụng bộ đệm bộ nhớ không hiệu quả (ví dụ) . Trong khi nhà phát triển gói SSIS có thể khai báo kích thước cột nhỏ hơn nguồn thì phân tích này tốt nhất nên được thực hiện trước và thực thi ở đó.

Quay lại bản thân công cụ SQL Server, một trường hợp tương tự là khi tính toán bộ nhớ cấp để phân bổ cho các SORThoạt động, SQL Server giả định rằngvarchar(x) các cột sẽ tiêu thụ trung bình các x/2byte.

Nếu hầu hết các varcharcột của bạn đầy hơn mức đó, điều này có thể dẫn đến các sorthoạt động tràn sangtempdb .

Trong trường hợp của bạn nếu các varcharcột của bạn được khai báo là8000 byte nhưng thực sự có nội dung ít hơn nhiều thì truy vấn của bạn sẽ được cấp phát bộ nhớ mà nó không yêu cầu, điều này rõ ràng là không hiệu quả và có thể dẫn đến việc chờ cấp bộ nhớ.

Điều này được đề cập trong Phần 2 của Webcast 1 của Hội thảo SQL có thể tải xuống từ đây hoặc xem bên dưới.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Ảnh chụp màn hình

SELECT id,name8000
FROM T
ORDER BY number

Ảnh chụp màn hình


1
vì vậy, nếu hầu như tất cả các giá trị của tôi là 3 hoặc 4 ký tự, không thể vượt quá 4 ký tự và tôi muốn tránh "hoạt động sắp xếp tràn sang tempdb", tôi sẽ khai báo cột VARCHAR (8) và sử dụng ràng buộc CHECK để thực thi cột đó chiều rộng không được vượt quá 4 ký tự. Bạn nghĩ sao?
AK

12
@AlexKuznetsov - Đối với tình huống đó, tôi sẽ khai báo chúng char(4)vì dù sao cũng có 2 byte chi phí trên mỗi cột biến.
Martin Smith

9

Ngoài các phương pháp hay nhất (câu trả lời của BBlake)

  • Bạn nhận được cảnh báo về kích thước hàng tối đa (8060) byte và chiều rộng chỉ mục (900 byte) với DDL
  • DML sẽ chết nếu bạn vượt quá các giới hạn này
  • ANSI PADDING ON là mặc định để bạn có thể lưu trữ một lượng lớn khoảng trắng

38
Chỉ cần làm rõ về ANSI PADDING ON: khi sử dụng nvarcharvarcharcác loại, điều này chỉ có nghĩa là các khoảng trống ở cuối được giữ nguyên khi chèn - không phải là các giá trị được đệm bằng các khoảng trắng bằng kích thước của cột, như trong charnchar.
Ben M

9

Có một số nhược điểm đối với các cột lớn mà ít rõ ràng hơn một chút và có thể bạn sẽ gặp sau một chút:

  • Tất cả các cột bạn sử dụng trong INDEX - không được vượt quá 900 byte
  • Tất cả các cột trong mệnh đề ORDER BY không được vượt quá 8060 byte. Điều này hơi khó nắm bắt vì điều này chỉ áp dụng cho một số cột. Xem SQL 2008 R2 Đã vượt quá giới hạn kích thước hàng để biết chi tiết)
  • Nếu tổng kích thước hàng vượt quá 8060 byte, bạn sẽ nhận được " tràn trang " cho hàng đó. Điều này có thể ảnh hưởng đến hiệu suất (Một trang là đơn vị phân bổ trong SQLServer và được cố định ở 8000 byte + một số chi phí. Vượt quá điều này sẽ không nghiêm trọng, nhưng nó đáng chú ý và bạn nên cố gắng tránh nó nếu bạn có thể dễ dàng)
  • Nhiều cấu trúc dữ liệu nội bộ khác, bộ đệm và cuối cùng không kém phần ngoại lệ và biến bảng của riêng bạn đều cần phản ánh các kích thước này. Với kích thước quá lớn, phân bổ bộ nhớ quá mức có thể ảnh hưởng đến hiệu suất

Theo nguyên tắc chung, hãy cố gắng thận trọng với chiều rộng cột. Nếu nó trở thành một vấn đề, bạn có thể dễ dàng mở rộng nó để phù hợp với nhu cầu. Nếu bạn nhận thấy các vấn đề về bộ nhớ sau đó, việc thu nhỏ một cột rộng sau đó có thể trở nên bất khả thi mà không làm mất dữ liệu và bạn sẽ không biết bắt đầu từ đâu.

Trong ví dụ của bạn về tên doanh nghiệp, hãy nghĩ về nơi bạn có thể hiển thị chúng. Có thực sự có khoảng trống cho 500 ký tự không ?? Nếu không, có rất ít điểm trong việc lưu trữ chúng như vậy. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States liệt kê một số tên công ty và tối đa là khoảng 50 ký tự. Vì vậy, tôi sẽ sử dụng 100 cho cột CPC Có thể giống hơn 80.


2

Lý tưởng nhất là bạn muốn nhỏ hơn mức đó, xuống độ dài có kích thước hợp lý (500 không phải là kích thước hợp lý) và đảm bảo xác thực ứng dụng bắt kịp khi dữ liệu quá lớn và gửi một lỗi hữu ích.

Trong khi varchar thực sự sẽ không dành không gian trong cơ sở dữ liệu cho không gian chưa sử dụng, tôi nhớ lại các phiên bản của SQL Server có một snit về các hàng cơ sở dữ liệu rộng hơn một số byte (không nhớ chính xác số lượng) và thực sự ném ra bất kỳ dữ liệu nào không phù hợp. Một số byte nhất định được dành riêng cho những thứ bên trong SQL Server.


đúng, điều này cũng từng là mối quan tâm lớn hơn nhiều. Nhưng ngày nay, không gian thực sự rẻ nên tôi không nghĩ đó là mối quan tâm lớn để xem xét, ít nhất là theo quan điểm của tôi.
BBlake

1
@jcollum: Trong ví dụ của bạn, 500 có vẻ không có kích thước hợp lý cho tên doanh nghiệp.
Otis

1
@BBlake: Bất kể chi phí lưu trữ, nếu SQL Server vẫn có các hạn chế về kích thước hàng thì không quan trọng bạn có bao nhiêu dung lượng lưu trữ. Bạn có thể lưu trữ mọi thứ trong textblob nhưng có một số thao tác SQL bạn không thể thực hiện trên blob mà bạn có thể thực hiện trên varchar.
Otis

2
@Otis: quan điểm của tôi là thế này: không có ràng buộc thực tế nào về quy mô của tên doanh nghiệp. Trừ khi có luật ở đâu đó. Vì vậy, trong trường hợp đó, tôi sẽ tạo trường đó varchar (8000) và gọi nó là một ngày. Suy nghĩ của tôi đi như thế này: Ràng buộc thực sự? varchar (x). Không có ràng buộc thực sự? varchar (8000).
jcollum

24
Tôi nghĩ khoảng 30 ký tự là phù hợp với tên thành phố, cho đến khi tôi thấy El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC
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.