Thực tiễn tốt nhất cho chiều dài cột varchar SQL [đã đóng]


288

Mỗi lần được thiết lập một bảng SQL mới hoặc thêm một varcharcột mới vào một bảng hiện có, tôi tự hỏi một điều: giá trị tốt nhất cho cái gì là length.

Vì vậy, giả sử, bạn có một cột được gọi là nameloại varchar. Vì vậy, bạn phải chọn chiều dài. Tôi không thể nghĩ ra một cái tên> 20 ký tự, nhưng bạn sẽ không bao giờ biết. Nhưng thay vì sử dụng 20, tôi luôn làm tròn đến số 2 ^ n tiếp theo. Trong trường hợp này, tôi sẽ chọn 32 là chiều dài. Tôi làm điều đó, bởi vì theo quan điểm của nhà khoa học máy tính, một số 2 ^ n evenđối với tôi nhiều hơn các số khác và tôi chỉ cho rằng kiến ​​trúc bên dưới có thể xử lý những số đó tốt hơn một chút so với các số khác.

Mặt khác, máy chủ MSSQL chẳng hạn, đặt giá trị độ dài mặc định là 50, khi bạn chọn tạo cột varchar. Điều đó khiến tôi suy nghĩ về nó. Tại sao 50? nó chỉ là một số ngẫu nhiên, hoặc dựa trên chiều dài cột trung bình, hay cái gì?

Cũng có thể - hoặc có thể là - các triển khai máy chủ SQL khác nhau (như MySQL, MSSQL, Postgres, ...) có các giá trị độ dài cột tốt nhất khác nhau.

Câu trả lời:


238

Không có DBMS nào tôi biết có bất kỳ "tối ưu hóa" nào sẽ làm cho VARCHARmột 2^nchiều dài hoạt động tốt hơn một maxchiều dài không phải là sức mạnh bằng 2.

Tôi nghĩ rằng các phiên bản SQL Server đầu tiên thực sự đã xử lý một VARCHARđộ dài 255 khác với một phiên bản có độ dài tối đa cao hơn. Tôi không biết nếu đây vẫn là trường hợp.

Đối với hầu hết tất cả DBMS, dung lượng lưu trữ thực tế được yêu cầu chỉ được xác định bởi số lượng ký tự bạn đặt vào nó, không phải maxđộ dài bạn xác định. Vì vậy, từ quan điểm lưu trữ (và rất có thể là hiệu suất cũng vậy), nó không tạo ra bất kỳ sự khác biệt nào cho dù bạn khai báo một cột là VARCHAR(100)hay VARCHAR(500).

Bạn sẽ thấy maxđộ dài được cung cấp cho một VARCHARcột là một loại ràng buộc (hoặc quy tắc kinh doanh) chứ không phải là một điều kỹ thuật / vật lý.

Đối với PostgreSQL, thiết lập tốt nhất là sử dụng textmà không giới hạn độ dài và CHECK CONSTRAINTgiới hạn số lượng ký tự cho bất kỳ doanh nghiệp nào của bạn yêu cầu.

Nếu yêu cầu đó thay đổi, việc thay đổi ràng buộc kiểm tra nhanh hơn nhiều so với thay đổi bảng (vì bảng không cần phải viết lại)

Điều tương tự có thể được áp dụng cho Oracle và những người khác - trong Oracle nó sẽ VARCHAR(4000)thay thế textmặc dù.

Tôi không biết có sự khác biệt về lưu trữ vật lý giữa VARCHAR(max)và vd VARCHAR(500)trong SQL Server không. Nhưng rõ ràng là có một tác động hiệu suất khi sử dụng varchar(max)so với varchar(8000).

Xem liên kết này (được đăng bởi Erwin Brandstetter dưới dạng bình luận)

Chỉnh sửa 2013-09-22

Về bình luận của Bigown:

Trong các phiên bản Postgres trước 9.2 (không có sẵn khi tôi viết câu trả lời ban đầu), một thay đổi đối với định nghĩa cột đã viết lại toàn bộ bảng, xem ví dụ ở đây . Kể từ 9.2, đây không còn là trường hợp nữa và một thử nghiệm nhanh đã xác nhận rằng việc tăng kích thước cột cho một bảng có 1,2 triệu hàng thực sự chỉ mất 0,5 giây.

Đối với Oracle điều này dường như cũng đúng, đánh giá theo thời gian cần thiết để thay đổi varcharcột của một bảng lớn . Nhưng tôi không thể tìm thấy bất kỳ tài liệu tham khảo cho điều đó.

Đối với MySQL , hướng dẫn sử dụng có nội dung " Trong hầu hết các trường hợp, hãy ALTER TABLEtạo một bản sao tạm thời của bảng gốc ". Và các thử nghiệm của riêng tôi xác nhận rằng: chạy ALTER TABLEmột bảng trên 1,2 triệu hàng (giống như trong thử nghiệm của tôi với Postgres) để tăng kích thước của một cột mất 1,5 phút. Tuy nhiên, trong MySQL, bạn không thể sử dụng "cách giải quyết" để sử dụng ràng buộc kiểm tra để giới hạn số lượng ký tự trong một cột.

Đối với SQL Server, tôi không thể tìm thấy một tuyên bố rõ ràng về điều này nhưng thời gian thực hiện để tăng kích thước của một varcharcột (một lần nữa bảng 1,2 triệu hàng ở trên) chỉ ra rằng không có ghi lại diễn ra.

Chỉnh sửa 2017-01-24

Có vẻ như tôi (ít nhất là một phần) sai về SQL Server. Xem câu trả lời này của Aaron Bertrand cho thấy độ dài được khai báo của một nvarcharhoặc varcharcác cột tạo ra sự khác biệt rất lớn cho hiệu suất.


34
Trên thực tế, có một sự khác biệt giữa VARCHAR (255) và VARCHAR (500), ngay cả khi bạn đặt 1 ký tự bên trong cột đó. Giá trị được nối ở cuối hàng sẽ là một số nguyên lưu trữ độ dài thực của dữ liệu được lưu trữ. Trong trường hợp VARCHAR (255), nó sẽ là số nguyên 1 byte. Trong trường hợp VARCHAR (500), nó sẽ là 2 byte. đó là một sự khác biệt nhỏ, nhưng người ta nên nhận thức về nó. Tôi không có bất kỳ dữ liệu nào trong tay về việc nó có thể ảnh hưởng đến hiệu suất như thế nào, nhưng tôi cho rằng nó quá nhỏ đến mức không đáng để nghiên cứu.
NB

1
@NB: đó là những gì tôi đã đề cập đến cho giá trị 255 "ma thuật" của SQL Server. Cảm ơn bạn đã làm rõ.
a_horse_with_no_name

4
@NB Bạn đang đề cập đến RDBMS nào? Máy chủ SQL? Có ảnh hưởng đến hiệu suất. [N] VARCHAR (tối đa) hoạt động chậm hơn một chút so với [N] VARCHAR (n). Gần đây tôi đã được đề cập đến trang web này . Điều tương tự không đúng với PostgreSQL đối với tất cả những gì tôi biết.
Erwin Brandstetter

@ErwinBrandstetter: Cảm ơn đã liên kết. Có vẻ như varchar(max)có lẽ giống với Oracle hơnCLOB
a_horse_with_no_name

1
Thay đổi độ dài varchar không viết lại bảng. Nó chỉ kiểm tra độ dài ràng buộc đối với toàn bộ bảng chính xác như KIỂM TRA CONSTRAINT. Nếu bạn tăng chiều dài thì không có gì để làm, chỉ cần chèn hoặc cập nhật tiếp theo sẽ chấp nhận độ dài lớn hơn. Nếu bạn giảm độ dài và tất cả các hàng vượt qua ràng buộc nhỏ hơn mới, PG sẽ không thực hiện thêm bất kỳ hành động nào bên cạnh việc cho phép các lần chèn hoặc cập nhật tiếp theo chỉ ghi độ dài mới.
Maniero

69

VARCHAR(255)VARCHAR(2)lấy chính xác cùng một dung lượng trên đĩa! Vì vậy, lý do duy nhất để hạn chế nó là nếu bạn có nhu cầu cụ thể để nó nhỏ hơn. Nếu không, làm cho tất cả 255.

Cụ thể, khi thực hiện sắp xếp, cột lớn hơn chiếm nhiều không gian hơn, vì vậy nếu điều đó làm tổn hại đến hiệu suất, thì bạn cần phải lo lắng về nó và làm cho chúng nhỏ hơn. Nhưng nếu bạn chỉ chọn 1 hàng từ bảng đó, thì bạn có thể tạo tất cả 255 và điều đó không thành vấn đề.

Xem: các kích thước varchar tối ưu cho MySQL là gì?


7
Tại sao không làm cho tất cả VARCHAR(MAX)? Không gian không phải là sự cân nhắc duy nhất khi mô hình hóa một cơ sở dữ liệu. Tên miền bạn đang tạo mô hình nên điều khiển các loại dữ liệu và kích thước.
Oded

6
@Oded VARCHAR(MAX)không giống như varchar(255)hoặc varchar(65535)- varchar max là một kiểu textdữ liệu. Và theo quan điểm của bạn - nếu anh ta biết "miền anh ta đang làm mẫu" thì anh ta sẽ không hỏi câu hỏi này. Rõ ràng anh ta không biết dữ liệu của mình sẽ lớn đến mức nào, và tôi trấn an anh ta rằng làm cho nó có kích thước đầy đủ không làm tổn hại gì.
Ariel

4
@Ariel: Có những vấn đề và giới hạn về chỉ số để xem xét, quá. Bạn không thể có một (a,b,c,d)chỉ mục khi tất cả bốn cột VARCHAR(255).
ypercubeᵀᴹ

@ypercube Điều đó đúng, nếu các cột của bạn cần một chỉ mục, bạn cần cẩn thận hơn với các kích thước. Nhưng hầu hết các cột không cần một chỉ mục nên hầu hết thời gian bạn không cần phải lo lắng về nó.
Ariel

Tôi nghĩ rằng nếu chúng ta biết giá trị chính xác tôi thích sử dụng char. Trong khi đó, nếu vẫn còn dự đoán, tôi sử dụng varchar và giữ 255 vì đây là cấp phát bộ nhớ động nên bạn không lo lắng về kích thước sẽ được thực hiện
Faris Rayhan

54

Bất cứ khi nào tôi thiết lập một bảng SQL mới, tôi cũng cảm thấy như vậy về việc 2 "n" thậm chí còn hơn ... nhưng để tổng hợp các câu trả lời ở đây, không có tác động đáng kể nào đến không gian lưu trữ chỉ bằng cách xác định varchar (2 ^ n) hoặc thậm chí varchar (MAX).

Điều đó nói rằng, bạn vẫn nên dự đoán những tác động tiềm năng đối với việc lưu trữ và hiệu suất khi đặt giới hạn varchar () cao. Ví dụ: giả sử bạn tạo một cột varchar (MAX) để giữ các mô tả sản phẩm với lập chỉ mục toàn văn. Nếu 99% các mô tả chỉ dài 500 ký tự, và sau đó đột nhiên bạn nhận được ai đó thay thế các mô tả đã nói bằng các bài viết trên wikipedia, bạn có thể nhận thấy các lượt truy cập hiệu suất và lưu trữ đáng kể.

Một điều khác cần xem xét từ Bill Karwin :

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

Về cơ bản, chỉ cần đưa ra các ràng buộc kinh doanh hợp lý và lỗi trên một kích thước lớn hơn một chút. Như @encedaywhen đã chỉ ra, tên gia đình ở Anh thường nằm trong khoảng 1-35 ký tự. Nếu bạn quyết định biến nó thành varchar (64), bạn sẽ không thực sự làm tổn thương bất cứ điều gì ... trừ khi bạn lưu trữ tên gia đình của anh chàng này được cho là dài tới 666 ký tự. Trong trường hợp đó, có thể varchar (1028) có ý nghĩa hơn.

Và trong trường hợp nó hữu ích, đây là varchar 2 ^ 5 đến 2 ^ 10 có thể trông như thế nào nếu được điền:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit

31

Giá trị tốt nhất là giá trị phù hợp với dữ liệu như được xác định trong miền bên dưới.

Đối với một số tên miền, VARCHAR(10)phù hợp với Namethuộc tính, đối với các tên miền khác VARCHAR(255)có thể là lựa chọn tốt nhất.


15

Thêm vào câu trả lời của a_horse_with_no_name, bạn có thể tìm thấy những điều thú vị sau ...

nó không tạo ra bất kỳ sự khác biệt nào cho dù bạn khai báo một cột là VARCHAR (100) hay VACHAR (500).

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

Đừng quên (các) byte độ dài và byte nullable để:

name varchar(100) not null sẽ là 1 byte (chiều dài) + tối đa 100 ký tự (latin1)

name varchar(500) not null sẽ là 2 byte (chiều dài) + tối đa 500 ký tự (latin1)

name varchar(65533) not null sẽ là 2 byte (chiều dài) + tối đa 65533 ký tự (latin1)

name varchar(65532) sẽ là 2 byte (độ dài) + tối đa 65532 ký tự (latin1) + 1 byte null

Hi vọng điêu nay co ich :)


Bạn đang sử dụng MySQL và câu hỏi là về MSSQL
Bogdan Mart

6

Luôn luôn kiểm tra với chuyên gia lĩnh vực kinh doanh của bạn. Nếu đó là bạn, hãy tìm một tiêu chuẩn công nghiệp. Ví dụ: nếu tên miền được đề cập là tên gia đình của người tự nhiên (họ) thì đối với một doanh nghiệp ở Vương quốc Anh, tôi sẽ truy cập danh mục tiêu chuẩn dữ liệu Govtalk của Vương quốc Anh để biết thông tin cá nhân và khám phá rằng tên gia đình sẽ có từ 1 đến 35 ký tự .


3

Gần đây tôi đã không kiểm tra điều này, nhưng tôi biết trong quá khứ với Oracle rằng trình điều khiển JDBC sẽ dự trữ một đoạn bộ nhớ trong khi thực hiện truy vấn để giữ tập kết quả quay trở lại. Kích thước của khối bộ nhớ phụ thuộc vào định nghĩa cột và kích thước tìm nạp. Vì vậy, độ dài của các cột varchar2 ảnh hưởng đến dung lượng bộ nhớ được dự trữ. Điều này gây ra các vấn đề hiệu suất nghiêm trọng đối với tôi nhiều năm trước vì chúng tôi luôn sử dụng varchar2 (4000) (mức tối đa tại thời điểm đó) và việc thu gom rác kém hiệu quả hơn nhiều so với ngày nay.


-2

Theo một nghĩa nào đó, bạn đúng, mặc dù mọi thứ thấp hơn 2 ^ 8 ký tự vẫn sẽ đăng ký dưới dạng một byte dữ liệu.

Nếu bạn tính đến ký tự cơ sở để lại bất cứ thứ gì có VARCHAR <255 thì sẽ tiêu tốn cùng một dung lượng.

255 là một định nghĩa cơ bản tốt trừ khi bạn đặc biệt muốn giảm bớt đầu vào quá mức.


" mặc dù mọi thứ thấp hơn 2 ^ 8 ký tự vẫn sẽ đăng ký dưới dạng một byte dữ liệu " - sai. Cơ sở dữ liệu chỉ lưu trữ nhiều ký tự như được cung cấp trong loại VARCHAR. Không có khoảng trắng nào được "đăng ký", dành riêng hoặc khởi tạo khi khai báo một cột.
a_horse_with_no_name
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.