Các trường hợp sử dụng để chọn CHAR trên VARCHAR trong SQL là gì?


270

Tôi nhận ra rằng CHAR được khuyến nghị nếu tất cả các giá trị của tôi là chiều rộng cố định. Nhưng cái gì cơ? Tại sao không chọn VARCHAR cho tất cả các trường văn bản để an toàn.

Câu trả lời:


386

Thường chọn CHAR nếu tất cả các hàng sẽ có cùng độ dài . Chọn VARCHAR khi chiều dài thay đổi đáng kể. CHAR cũng có thể nhanh hơn một chút vì tất cả các hàng có cùng độ dài.

Nó thay đổi theo cách triển khai DB, nhưng nói chung VARCHAR sử dụng một hoặc hai byte lưu trữ (cho độ dài hoặc chấm dứt) ngoài dữ liệu thực tế. Vì vậy (giả sử bạn đang sử dụng bộ ký tự một byte) lưu trữ từ "FooBar"

  • CHAR (6) = 6 byte (không có phí)
  • VARCHAR (10) = 8 byte (2 byte trên không)
  • CHAR (10) = 10 byte (4 byte trên không)

Dòng dưới cùng là CHAR có thể nhanh hơn và tiết kiệm không gian hơn cho dữ liệu có độ dài tương đối giống nhau (trong phạm vi chênh lệch hai ký tự).

Lưu ý : Microsoft SQL có 2 byte phí cho VARCHAR. Điều này có thể thay đổi từ DB sang DB, nhưng nhìn chung cần có ít nhất 1 byte chi phí cần thiết để biểu thị độ dài hoặc EOL trên VARCHAR.

Như đã được Gaven chỉ ra trong các nhận xét, nếu bạn đang sử dụng bộ ký tự có độ dài thay đổi nhiều byte như UTF8 thì CHAR lưu trữ số byte tối đa cần thiết để lưu trữ số lượng ký tự. Vì vậy, nếu UTF8 cần tối đa 3 byte để lưu trữ một ký tự, thì CHAR (6) sẽ được sửa ở mức 18 byte, ngay cả khi chỉ lưu trữ các ký tự latin1. Vì vậy, trong trường hợp này VARCHAR trở thành một lựa chọn tốt hơn nhiều.


20
Một lý do khác là chia trang và phân mảnh. Tôi đã có một bảng với PK IDEN bị phân mảnh 99% do phân chia trang trên các cột varchar. Một bảng rất tích cực và theo bản chất của ứng dụng, một hàng trống mới sẽ được tạo và sau đó được điền. Char đã sửa lỗi phân mảnh.
paparazzo

12
@Jim McKeeth - những tính toán này chỉ đúng nếu bạn đang sử dụng bộ ký tự latin1. Vì hầu hết mọi người nên sử dụng utf8 trong những ngày này, các cột CHAR của bạn sẽ sử dụng trung bình gấp 3 lần dung lượng vì VARCHAR lưu trữ hầu hết các ký tự trong mặt phẳng đa ngôn ngữ cơ sở.
Gavin Towey 17/03/2016

11
@JimMcKeeth vâng, điều đó hoàn toàn chính xác. Vì CHAR là chiều dài cố định, do đó nó phải được cố định ở không gian tối đa có thể được sử dụng. Trong UTF8 đó là 3 byte cho mỗi ký tự. Đối với varchar, bạn có thể sử dụng 1-3 byte cho mỗi ký tự nếu cần. Đây là trong hướng dẫn sử dụng MySQL: dev.mysql.com/doc/refman/5.0/en/charset-unicode-utf8.html
Gavin Towey

3
Sự khác biệt với chuỗi FooBar và varchar (100) so với char (100) là gì? Tôi đang nghĩ rằng chứng minh sự khác biệt tốt hơn, phải không? Không?
Nenotlep

4
@GavinTowey SQLSERVER sử dụng UCS-2 cho các kiểu dữ liệu NCHAR và NVARCHAR của nó. Nó luôn luôn là hai byte cho mỗi ký tự.
1010

69

Nếu bạn đang làm việc với tôi và bạn đang làm việc với Oracle, có lẽ tôi sẽ khiến bạn sử dụng varchartrong hầu hết mọi trường hợp. Giả định charsử dụng ít sức mạnh xử lý hơn varcharcó thể đúng ... hiện tại ... nhưng các công cụ cơ sở dữ liệu trở nên tốt hơn theo thời gian và loại quy tắc chung này đã tạo nên một "huyền thoại" trong tương lai.

Một điều nữa: Tôi chưa bao giờ thấy một vấn đề hiệu suất bởi vì ai đó đã quyết định đi cùng varchar. Bạn sẽ sử dụng tốt hơn nhiều thời gian của mình để viết mã tốt (ít cuộc gọi đến cơ sở dữ liệu) và SQL hiệu quả (cách các chỉ mục hoạt động, cách trình tối ưu hóa đưa ra quyết định, tại sao existsnhanh hơn bình inthường ...).

Suy nghĩ cuối cùng: Tôi đã thấy tất cả các loại vấn đề khi sử dụng CHAR, mọi người đang tìm kiếm '' khi họ nên tìm kiếm '' hoặc mọi người tìm kiếm 'FOO' khi họ nên tìm kiếm 'FOO (bó không gian ở đây)' hoặc mọi người không cắt xén các khoảng trống theo sau hoặc các lỗi với Powerbuilder thêm tối đa 2000 khoảng trống vào giá trị mà nó trả về từ một thủ tục Oracle.


20
Tôi không đồng ý với đoạn đầu tiên của bạn, vì char có thể cung cấp một gợi ý có thể hữu ích cho các trình tối ưu hóa, ngay cả những người trong tương lai và nó có thể giúp truyền đạt ý định của cột. Nhưng +1 cho đoạn thứ ba của bạn. Tôi ghét tất cả các không gian thêm. Một trường chỉ nên lưu trữ bất cứ thứ gì tôi đặt vào nó mà không cần tất cả các phần đệm [khám phá]. Về cơ bản, tôi chỉ sử dụng char nếu tất cả các dữ liệu có độ dài chính xác như nhau, không hơn không kém, bây giờ và mãi mãi. Điều này là rất hiếm, tất nhiên, và thường là một char (1).
Jeffrey L Whitledge

char cũng cung cấp một gợi ý cho các nhà phân tích và nhà phát triển ... điều này là x số ký tự .... Nếu họ đang nghĩ đến việc tuần tự hóa nó ở một số định dạng khác, điều đó có thể hữu ích. (Tôi đã buộc phải lưu trữ tổng kiểm tra md5 trong một char trong mssql không có loại uuid ... và tôi không bao giờ muốn bất cứ điều gì <32 byte ... cũng đặt một ràng buộc trên cột).
tham gia

31

Ngoài các lợi ích về hiệu suất, CHARcó thể được sử dụng để chỉ ra rằng tất cả các giá trị phải có cùng độ dài, ví dụ: một cột cho các chữ viết tắt của tiểu bang Hoa Kỳ.


Hoặc mã quốc gia - có thể giúp phân biệt giữa việc sử dụng tên viết tắt mã quốc gia 2 hoặc 3 ký tự
Dan Field

Nếu nó thực sự là một chiều dài cố định, thì cần phải có một ràng buộc thực thi điều đó. Mặc dù nếu bạn sử dụng CHAR, bạn sẽ phải đảm bảo phần đệm giảm giá ràng buộc.
jpmc26

18

Char nhanh hơn một chút, vì vậy nếu bạn có một cột mà bạn BIẾT sẽ có độ dài nhất định, hãy sử dụng char. Ví dụ: lưu trữ (M) ale / (F) emale / (U) được biết đến theo giới tính hoặc 2 ký tự cho một tiểu bang Hoa Kỳ.


4
Không chắc đó là câu trả lời TUYỆT VỜI, vì ENUM thường sẽ có ý nghĩa hơn rất nhiều, mặc dù tôi không chắc loại đó được hỗ trợ rộng rãi như thế nào (bên ngoài MySQL).
Bobby Jack

Dường như với tôi rằng tập hợp các trạng thái không nhất thiết là bất biến, vì vậy char (2) có vẻ phù hợp hơn nhiều so với một enum.
Kearns

1
@Bulk Jack - Tôi không biết chi tiết cụ thể của bất kỳ triển khai SQL enum cụ thể nào, nhưng hãy nhớ rằng một enum được lưu trữ dưới dạng số nguyên 4 byte có thể cần nhiều không gian hơn cột char (1) hoặc char (2) với cùng dữ liệu. Có một ý nghĩa trong đó các enum hợp lý hơn về mặt diễn giải của chúng và điều đó có thể hấp dẫn, nhưng mọi thứ trong hệ thống RDBMS đều trừu tượng ở một mức độ nào đó và tuân theo các vị từ được định nghĩa cho các bảng.
Jeffrey L Whitledge

4
Ví dụ xấu, ENUM là tốt nhất cho trường hợp đó. Ví dụ tốt hơn sẽ là mã sân bay IATA gồm 3 chữ cái
Andrew G. Johnson

5
@Andrew, không phải tất cả các loại dữ liệu ENUM hỗ trợ của db. MSSQLServer, ví dụ, không. Ngoài ra, một ENUM, được lưu trữ dưới dạng int, mất 4 byte. CHAR (1) mất 1 byte và NCHAR (1) mất 2 byte.
Jarrett Meyer

17

NChar hoặc Char thực hiện tốt hơn các lựa chọn thay thế var của họ?

Câu hỏi tuyệt vời. Câu trả lời đơn giản là có trong một số tình huống. Hãy xem điều này có thể được giải thích.

Rõ ràng tất cả chúng ta đều biết rằng nếu tôi tạo một bảng có cột varchar (255) (hãy gọi cột này là myColumn) và chèn một triệu hàng nhưng chỉ đặt một vài ký tự vào myColumn cho mỗi hàng, thì bảng sẽ nhỏ hơn nhiều (tổng thể số lượng trang dữ liệu cần thiết cho công cụ lưu trữ) so với khi tôi đã tạo myColumn là char (255). Bất cứ khi nào tôi thực hiện một thao tác (DML) trên bảng đó và yêu cầu rất nhiều hàng, sẽ nhanh hơn khi myColumn là varchar vì tôi không phải di chuyển xung quanh tất cả các khoảng trắng "phụ" đó ở cuối. Di chuyển, như khi SQL Server thực hiện các sắp xếp nội bộ, chẳng hạn như trong một hoạt động riêng biệt hoặc hợp nhất hoặc nếu nó chọn hợp nhất trong kế hoạch truy vấn của nó, v.v.

Nhưng có một số chi phí trong việc sử dụng varchar. SQL Server phải sử dụng một chỉ báo hai byte (trên cao) để, trên mỗi hàng, để biết có bao nhiêu byte mà myColumn của hàng cụ thể có trong đó. Đây không phải là 2 byte bổ sung gây ra vấn đề, đó là việc phải "giải mã" độ dài của dữ liệu trong myColumn trên mỗi hàng.

Theo kinh nghiệm của tôi, điều hợp lý nhất là sử dụng char thay vì varchar trên các cột sẽ được nối vào trong các truy vấn. Ví dụ, khóa chính của bảng hoặc một số cột khác sẽ được lập chỉ mục. Số khách hàng trên bảng nhân khẩu học hoặc CodeID trên bảng giải mã hoặc có lẽ là OrderNumber trên bảng đơn hàng. Bằng cách sử dụng char, công cụ truy vấn có thể thực hiện phép nối nhanh hơn vì nó có thể thực hiện số học con trỏ thẳng (xác định) thay vì phải di chuyển con trỏ của nó một lượng byte khác nhau khi đọc các trang. Tôi biết tôi có thể đã mất bạn trong câu cuối cùng đó. Tham gia trong SQL Server dựa trên ý tưởng về "vị ngữ". Một vị ngữ là một điều kiện. Ví dụ: myColumn = 1 hoặc OrderNumber <500.

Vì vậy, nếu SQL Server đang thực hiện một câu lệnh DML và các biến vị ngữ hoặc "khóa" được nối vào có độ dài cố định (char), thì công cụ truy vấn không phải thực hiện nhiều công việc để khớp các hàng từ một bảng với các hàng từ bàn khác. Nó sẽ không phải tìm ra dữ liệu trong hàng bao lâu và sau đó đi xuống chuỗi để tìm kết thúc. Tất cả điều đó cần có thời gian.

Bây giờ hãy nhớ rằng điều này có thể dễ dàng được thực hiện kém. Tôi đã thấy char được sử dụng cho các trường khóa chính trong các hệ thống trực tuyến. Chiều rộng phải được giữ nhỏ, ví dụ char (15) hoặc một cái gì đó hợp lý. Và nó hoạt động tốt nhất trong các hệ thống trực tuyến vì bạn thường chỉ truy xuất hoặc tăng số lượng hàng nhỏ, do đó, phải "kiểm tra lại" các khoảng trống đó bạn sẽ nhận được trong tập kết quả là một nhiệm vụ không quan trọng so với việc phải tham gia hàng triệu các hàng từ một bảng đến hàng triệu hàng trên một bảng khác.

Một lý do khác khiến CHAR có ý nghĩa đối với varchar trên các hệ thống trực tuyến là nó làm giảm sự phân chia trang. Bằng cách sử dụng char, về cơ bản, bạn sẽ "dự trữ" (và lãng phí) không gian đó, vì vậy nếu người dùng xuất hiện sau đó và đặt thêm dữ liệu vào cột đó thì SQL đã phân bổ không gian cho nó và sẽ đi vào đó.

Một lý do khác để sử dụng CHAR tương tự như lý do thứ hai. Nếu một lập trình viên hoặc người dùng thực hiện cập nhật "lô" lên hàng triệu hàng, chẳng hạn như thêm một số câu vào trường ghi chú, bạn sẽ không nhận được cuộc gọi từ DBA vào giữa đêm, tự hỏi tại sao ổ đĩa của họ lại đầy. Nói cách khác, nó dẫn đến sự tăng trưởng dễ dự đoán hơn về kích thước của cơ sở dữ liệu.

Vì vậy, đó là 3 cách mà một hệ thống trực tuyến (OLTP) có thể được hưởng lợi từ char hơn varchar. Tôi hầu như không bao giờ sử dụng char trong kịch bản kho / phân tích / OLAP bởi vì thông thường bạn có quá nhiều dữ liệu mà tất cả các cột char đó có thể thêm vào nhiều không gian lãng phí.

Hãy nhớ rằng char có thể làm cho cơ sở dữ liệu của bạn lớn hơn nhiều nhưng hầu hết các công cụ sao lưu đều nén dữ liệu để các bản sao lưu của bạn có xu hướng có cùng kích thước như khi bạn sử dụng varchar. Ví dụ: Sao lưu SQL LiteSpeed ​​hoặc RedGate.

Một cách sử dụng khác là trong các khung nhìn được tạo để xuất dữ liệu sang tệp có chiều rộng cố định. Giả sử tôi phải xuất một số dữ liệu sang tệp phẳng để được máy tính lớn đọc. Đó là chiều rộng cố định (không phân định). Tôi muốn lưu trữ dữ liệu trong bảng "dàn" của mình dưới dạng varchar (do đó tiêu tốn ít dung lượng hơn trên cơ sở dữ liệu của tôi) và sau đó sử dụng chế độ xem để CAST mọi thứ tương đương với char, với chiều dài tương ứng với chiều rộng của chiều rộng cố định cho cột đó . Ví dụ:

create table tblStagingTable (
pkID BIGINT (IDENTITY,1,1),
CustomerFirstName varchar(30),
CustomerLastName varchar(30),
CustomerCityStateZip varchar(100),
CustomerCurrentBalance money )

insert into tblStagingTable
(CustomerFirstName,CustomerLastName, CustomerCityStateZip) ('Joe','Blow','123 Main St Washington, MD 12345', 123.45)

create view vwStagingTable AS
SELECT CustomerFirstName = CAST(CustomerFirstName as CHAR(30)),
CustomerLastName = CAST(CustomerLastName as CHAR(30)),
CustomerCityStateZip = CAST(CustomerCityStateZip as CHAR(100)),
CustomerCurrentBalance = CAST(CAST(CustomerCurrentBalance as NUMERIC(9,2)) AS CHAR(10))

SELECT * from vwStagingTable

Điều này thật tuyệt vì bên trong dữ liệu của tôi chiếm ít không gian hơn vì nó sử dụng varchar. Nhưng khi tôi sử dụng DTS hoặc SSIS hoặc thậm chí chỉ là cắt và dán từ SSMS sang Notepad, tôi có thể sử dụng chế độ xem và nhận đúng số lượng khoảng trắng ở cuối. Trong DTS, chúng tôi đã từng có một tính năng được gọi là, tôi quên tôi nghĩ rằng nó được gọi là "cột gợi ý" hoặc một cái gì đó. Trong SSIS, bạn không thể làm điều đó nữa, bạn phải xác định một cách tẻ nhạt trình quản lý kết nối tệp phẳng. Nhưng vì bạn đã thiết lập chế độ xem của mình, SSIS có thể biết chiều rộng của mỗi cột và nó có thể tiết kiệm rất nhiều thời gian khi xây dựng các tác vụ luồng dữ liệu của bạn.

Vì vậy, dòng dưới cùng ... sử dụng varchar. Có một số lý do rất nhỏ để sử dụng char và nó chỉ vì lý do hiệu suất. Nếu bạn có một hệ thống với hàng triệu hàng, bạn sẽ thấy một sự khác biệt đáng chú ý nếu các vị từ có tính xác định (char) nhưng đối với hầu hết các hệ thống sử dụng char chỉ đơn giản là lãng phí không gian.

Mong rằng sẽ giúp. Jeff


Bạn đang nói trò chuyện cố định chiếm nhiều không gian hơn không chỉ khi được lưu trữ mà cả khi được vận chuyển hoặc "di chuyển" như bạn nói? Từ máy chủ DB đến máy khách của tôi chẳng hạn? Khi nào chúng ta mất các byte null?
Hạt đậu đỏ

9

Có những lợi ích về hiệu suất, nhưng đây là một lợi ích chưa được đề cập: di chuyển hàng. Với char, bạn đặt trước toàn bộ không gian. Vì vậy, giả sử bạn có char (1000) và bạn lưu trữ 10 ký tự, bạn sẽ sử dụng hết 1000 charaters của không gian. Trong một varchar2 (1000), bạn sẽ chỉ sử dụng 10 ký tự. Vấn đề xảy ra khi bạn sửa đổi dữ liệu. Giả sử bạn cập nhật cột để chứa 900 ký tự. Có thể là không gian để mở rộng varchar không có sẵn trong khối hiện tại. Trong trường hợp đó, công cụ DB phải di chuyển hàng sang khối khác và tạo một con trỏ trong khối ban đầu sang hàng mới trong khối mới. Để đọc dữ liệu này, công cụ DB bây giờ sẽ phải đọc 2 khối.
Không ai có thể nói một cách bình đẳng rằng varchar hoặc char là tốt hơn. Có một không gian cho sự đánh đổi thời gian và xem xét liệu dữ liệu sẽ được cập nhật hay không, đặc biệt nếu có cơ hội tốt để nó phát triển.


Tôi nghĩ rằng bạn có một lỗi đánh máy trong bài viết của mình - không nên varchar2 (1000) là CHAR (1000)?
Matt Rogish

8

Có một sự khác biệt giữa tối ưu hóa hiệu suất sớm và sử dụng loại quy tắc thực hành tốt nhất. Nếu bạn đang tạo các bảng mới, nơi bạn sẽ luôn có một trường có độ dài cố định, sẽ rất hợp lý khi sử dụng CHAR, bạn nên sử dụng nó trong trường hợp đó. Đây không phải là tối ưu hóa sớm, mà là thực hiện quy tắc ngón tay cái (hoặc thực hành tốt nhất).

tức là - Nếu bạn có trường trạng thái 2 chữ cái, hãy sử dụng CHAR (2). Nếu bạn có một trường có tên trạng thái thực tế, hãy sử dụng VARCHAR.


8

Tôi sẽ chọn varchar trừ khi cột lưu trữ giá trị cố định như mã tiểu bang Hoa Kỳ - luôn dài 2 ký tự và danh sách mã tiểu bang hợp lệ của Hoa Kỳ không thay đổi thường xuyên :).

Trong mọi trường hợp khác, ngay cả khi lưu trữ mật khẩu băm (có độ dài cố định), tôi sẽ chọn varchar.

Tại sao - cột loại char luôn được thỏa mãn với khoảng trắng, điều này làm cho cột my_column được định nghĩa là char (5) với giá trị 'ABC' bên trong so sánh:

my_column = 'ABC' -- my_column stores 'ABC  ' value which is different then 'ABC'

sai.

Đây tính năng có thể dẫn đến nhiều lỗi khó chịu quá trình phát triển và làm cho thử nghiệm khó khăn hơn.


1
Ít nhất là trong Máy chủ MSSQL, 'abc' = 'abc'. Tôi chưa bao giờ tìm ra nếu tôi thích hoặc ghét tính năng đó ....
Mark Brackett

Đọc tốt về phần đệm của char ở đây Padding
Edward

6

CHAR chiếm ít không gian lưu trữ hơn VARCHAR nếu tất cả các giá trị dữ liệu của bạn trong trường đó có cùng độ dài. Bây giờ có lẽ trong năm 2009, cơ sở dữ liệu 800 GB là giống nhau cho tất cả các mục đích và mục đích là 810GB nếu bạn chuyển đổi VARCHAR thành CHAR, nhưng đối với các chuỗi ngắn (1 hoặc 2 ký tự), CHAR vẫn là một "cách thực hành tốt nhất" trong ngành.

Bây giờ nếu bạn nhìn vào nhiều loại dữ liệu khác nhau, hầu hết các cơ sở dữ liệu cung cấp ngay cả cho các số nguyên một mình (bit, tiny, int, bigint), có nhiều lý do để chọn loại dữ liệu này. Đơn giản chỉ cần chọn bigint mỗi lần thực sự là một chút không biết gì về mục đích và mục đích sử dụng của lĩnh vực này. Nếu một lĩnh vực chỉ đơn giản là đại diện cho một người trong nhiều năm, một bigint là quá mức cần thiết. Bây giờ không nhất thiết là "sai", nhưng nó không hiệu quả.

Nhưng đó là một đối số thú vị và khi cơ sở dữ liệu cải thiện theo thời gian, có thể tranh cãi CHAR vs VARCHAR sẽ ít liên quan hơn.


4

Tôi đứng trước bình luận của Jim McKeeth.

Ngoài ra, lập chỉ mục và quét toàn bộ bảng sẽ nhanh hơn nếu bảng của bạn chỉ có các cột CHAR. Về cơ bản, trình tối ưu hóa sẽ có thể dự đoán mỗi bản ghi lớn như thế nào nếu nó chỉ có các cột CHAR, trong khi nó cần kiểm tra giá trị kích thước của mỗi cột VARCHAR.

Ngoài ra, nếu bạn cập nhật cột VARCHAR lên kích thước lớn hơn nội dung trước đó, bạn có thể buộc cơ sở dữ liệu phải xây dựng lại các chỉ mục của nó (vì bạn buộc cơ sở dữ liệu phải di chuyển bản ghi trên đĩa). Trong khi với các cột CHAR sẽ không bao giờ xảy ra.

Nhưng bạn có thể sẽ không quan tâm đến hiệu suất đạt được trừ khi bảng của bạn rất lớn.

Hãy nhớ những lời khôn ngoan của Djikstra. Tối ưu hóa hiệu suất sớm là gốc rễ của tất cả các ác.


4
Có một mức độ suy đoán trong bình luận của bạn. Tôi đã thấy các giả định hết lần này đến lần khác như thế này được kiểm tra và điều ngược lại chính xác là đúng. Vấn đề là nhiều kỹ sư sẽ lấy thông tin như thế này làm phúc âm. Xin vui lòng, tạo trường hợp thử nghiệm phản ánh tình huống thực tế của bạn.
Ethan Post

Ethan hoàn toàn chính xác. Điều này phụ thuộc vào việc triển khai mà bạn đang sử dụng mà không tham chiếu đến thực tế (Sản phẩm, Phiên bản) thì hoàn toàn vô dụng.
David Schmitt

Khi bạn cập nhật một CHARcột, các chỉ mục cũng cần được cập nhật. Không có sự khác biệt trong việc cập nhật cột VARCHAR hoặc CHAR về vấn đề đó. Hãy suy nghĩ về việc cập nhật FOOlên BAR.
a_horse_with_no_name

4

Nhiều người đã chỉ ra rằng nếu bạn biết độ dài chính xác của giá trị sử dụng CHAR có một số lợi ích. Nhưng trong khi lưu trữ các tiểu bang Hoa Kỳ dưới dạng CHAR (2) thì thật tuyệt vời ngày hôm nay, khi bạn nhận được thông báo từ việc bán hàng rằng 'Chúng tôi vừa thực hiện lần bán hàng đầu tiên tới Úc', bạn đang ở trong một thế giới đau khổ. Tôi luôn gửi để đánh giá quá cao thời gian tôi nghĩ rằng các trường sẽ cần phải thay vì dự đoán 'chính xác' để bao quát cho các sự kiện trong tương lai. VARCHAR sẽ giúp tôi linh hoạt hơn trong lĩnh vực này.


3

Tôi nghĩ trong trường hợp của bạn có lẽ không có lý do gì để không chọn Varchar. Nó mang lại cho bạn sự linh hoạt và như đã được đề cập bởi một số người trả lời, hiệu suất bây giờ là như vậy, ngoại trừ trong những trường hợp rất cụ thể, chúng tôi là người chết (trái ngược với Google DBA) sẽ không nhận thấy sự khác biệt.

Một điều thú vị đáng chú ý khi nói đến DB Các loại là sqlite (một cơ sở dữ liệu nhỏ phổ biến với hiệu suất khá ấn tượng) đặt mọi thứ vào cơ sở dữ liệu dưới dạng một chuỗi và các loại đang hoạt động.

Tôi luôn sử dụng VarChar và thường làm cho nó lớn hơn nhiều so với mức tôi cần. Ví dụ. 50 cho Firstname, như bạn nói tại sao không chỉ để an toàn.


3

Tôi sẽ KHÔNG BAO GIỜ sử dụng ký tự. Tôi đã có cuộc tranh luận này với nhiều người và họ luôn đưa ra những lời sáo rỗng mệt mỏi rằng char nhanh hơn. Tôi nói, nhanh hơn bao nhiêu? Chúng ta đang nói gì ở đây, mili giây, giây và nếu có bao nhiêu? Bạn đang nói với tôi bởi vì ai đó tuyên bố nó nhanh hơn vài mili giây, chúng ta có nên giới thiệu hàng tấn lỗi khó khắc phục vào hệ thống không?

Vì vậy, đây là một số vấn đề bạn sẽ gặp phải:

Mỗi trường sẽ được đệm, vì vậy bạn kết thúc với mã mãi mãi có RTRIMS ở mọi nơi. Đây cũng là một sự lãng phí không gian đĩa lớn cho các trường dài hơn.

Bây giờ hãy giả sử bạn có ví dụ tinh túy về trường char chỉ có một ký tự nhưng trường này là tùy chọn. Nếu ai đó chuyển một chuỗi rỗng vào trường đó, nó sẽ trở thành một khoảng trắng. Vì vậy, khi một ứng dụng / quy trình khác truy vấn nó, họ sẽ nhận được một khoảng trống, nếu họ không sử dụng rtrim. Chúng tôi đã có các tài liệu xml, tệp và các chương trình khác, chỉ hiển thị một khoảng trắng, trong các trường tùy chọn và phá vỡ mọi thứ.

Vì vậy, bây giờ bạn phải đảm bảo rằng bạn chuyển null và không phải chuỗi rỗng, đến trường char. Nhưng đó KHÔNG phải là cách sử dụng null. Đây là việc sử dụng null. Hãy nói rằng bạn nhận được một tập tin từ một nhà cung cấp

Tên | Giới tính | Thành phố

Bob | | Los Angeles

Nếu giới tính không được chỉ định hơn bạn nhập Bob, chuỗi trống và Los Angeles vào bảng. Bây giờ hãy nói rằng bạn nhận được tệp và thay đổi định dạng và giới tính của nó không còn được bao gồm mà là trong quá khứ.

Tên | Thành phố

Bob | Seattle

Bây giờ vì không bao gồm giới tính, tôi sẽ sử dụng null. Varchars hỗ trợ này mà không có vấn đề.

Char mặt khác thì khác. Bạn luôn phải gửi null. Nếu bạn từng gửi chuỗi rỗng, bạn sẽ kết thúc với một trường có khoảng trắng trong đó.

Tôi có thể tiếp tục với tất cả các lỗi mà tôi đã phải sửa từ các ký tự và trong khoảng 20 năm phát triển.


2

Có một số chi phí xử lý nhỏ trong việc tính toán kích thước thực tế cần thiết cho một giá trị cột và phân bổ không gian cho Varchar, vì vậy nếu bạn chắc chắn giá trị sẽ luôn kéo dài bao lâu, tốt hơn là sử dụng Char và tránh bị tấn công.


2

Đó là không gian cổ điển so với sự đánh đổi hiệu suất.

Trong MS SQL 2005, Varchar (hoặc NVarchar cho các làn đường yêu cầu hai byte cho mỗi ký tự, tức là tiếng Trung Quốc) có độ dài thay đổi. Nếu bạn thêm vào hàng sau khi nó được ghi vào đĩa cứng, nó sẽ định vị dữ liệu ở một vị trí không liên quan đến hàng ban đầu và dẫn đến phân mảnh các tệp dữ liệu của bạn. Điều này sẽ ảnh hưởng đến hiệu suất.

Vì vậy, nếu không gian không phải là vấn đề thì Char sẽ tốt hơn cho hiệu năng nhưng nếu bạn muốn giữ kích thước cơ sở dữ liệu xuống thì varchars sẽ tốt hơn.


2

Phân mảnh. Char dự trữ không gian và VarChar thì không. Chia trang có thể được yêu cầu để phù hợp với cập nhật cho varchar.


Do nhiều yếu tố khác, việc chia trang có thể xảy ra khi cập nhật một CHARcột.
Rick James

1

Khi sử dụng các giá trị varchar, SQL Server cần thêm 2 byte mỗi hàng để lưu trữ một số thông tin về cột đó trong khi nếu bạn sử dụng char thì không cần như vậy trừ khi bạn


0

Trong một số cơ sở dữ liệu SQL, VARCHAR sẽ được thêm vào kích thước tối đa của nó để tối ưu hóa các độ lệch, Đây là để tăng tốc độ quét toàn bộ bảng và chỉ mục.

Do đó, bạn không có bất kỳ khoản tiết kiệm không gian nào bằng cách sử dụng VARCHAR (200) so với CHAR (200)


3
Cơ sở dữ liệu nào triển khai VARCHAR theo cách đó?
Quân Arvin

5
Nghiêm túc mà nói, cơ sở dữ liệu nào thực hiện theo cách đó? Những gì bạn mô tả thường áp dụng cho CHAR, không phải VARCHAR.
Richard Simões

mysql sẽ chuyển đổi varchar thành ký tự nếu có char và varchar trong cùng một bảng.
Malfist

Giải thích của tôi về các nhận xét MySQL là điều này không áp dụng cho lưu trữ bảng chính, nhưng có thể có thể phù hợp với các bảng tạm thời, ví dụ. để nhóm / sắp xếp dữ liệu. dev.mysql.com/doc/refman/8.0/en/char.html stackoverflow.com/questions/262238/
Thomas W

0

Sử dụng CHAR (NCHAR) và VARCHAR (NVARCHAR) mang đến sự khác biệt trong cách máy chủ cơ sở dữ liệu lưu trữ dữ liệu. Người đầu tiên giới thiệu khoảng trống theo sau; Tôi đã gặp sự cố khi sử dụng nó với toán tử THÍCH trong các hàm SQL SERVER. Vì vậy, tôi phải làm cho nó an toàn bằng cách sử dụng VARCHAR (NVARCHAR) mọi lúc.

Ví dụ: nếu chúng ta có bảng TEST (ID INT, Status CHAR (1)) và bạn viết một hàm để liệt kê tất cả các bản ghi với một số giá trị cụ thể như sau:

CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'

Trong hàm này, chúng tôi hy vọng rằng khi chúng ta đặt tham số mặc định, hàm sẽ trả về tất cả các hàng, nhưng thực tế thì không. Thay đổi loại dữ liệu @Status thành VARCHAR sẽ khắc phục sự cố.


Điều này cũng có thể được thay đổi bởi ansi_padding Cách lấy các giá trị
Edward
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.