2008-11-23 26 views
47
  1. VARCHAR không lưu trữ các ký tự Unicode.
  2. NVARCHAR lưu trữ các ký tự Unicode.
  3. Ứng dụng của ngày hôm nay phải luôn tương thích với Unicode.
  4. NVARCHAR mất gấp đôi dung lượng lưu trữ.
  5. Điểm 4 không quan trọng vì không gian lưu trữ cực kỳ rẻ.

Ergo: Khi thiết kế cơ sở dữ liệu SQL Server hôm nay, bạn nên luôn sử dụng NVARCHAR.VARCHAR có hoàn toàn giống như năm 1990 không?

Đây có phải là lý do âm thanh không? Có ai không đồng ý với bất kỳ cơ sở nào không? Có lý do nào để chọn VARCHAR trên NVARCHAR ngay hôm nay không?

+0

Xem điều này quá http://stackoverflow.com/q/35366/27535 – gbn

+0

Đây không phải là lý do âm thanh, chủ yếu là do cơ sở không hợp lệ. Mục 3 quá rộng của một tuyên bố. Mục 4 đã lỗi thời một phần vì SQL Server 2008 đã giới thiệu PAGE và ROW Compression, và 2008 R2 đã thêm (tự động/hậu trường) Unicode Compression (nhưng Compression chỉ có sẵn trong Enterprise Edition). Mục 5 vô lý sai. Vui lòng xem câu trả lời của tôi ở đây để biết chi tiết: http://stackoverflow.com/a/32871477/577765 –

Trả lời

48

Bạn khớp với kiểu dữ liệu với dữ liệu sẽ được lưu trữ trong cột. Bởi một đối số tương tự, bạn có thể nói lý do tại sao không lưu trữ tất cả dữ liệu trong cột NVARCHAR, vì số và ngày tháng có thể được biểu diễn dưới dạng chuỗi các chữ số.

Nếu kết hợp tốt nhất cho dữ liệu sẽ được lưu trữ trong cột là VARCHAR, thì hãy sử dụng nó.

1

Tôi không có chuyên gia về chủ đề này. Nhưng tại sao bạn không thể sử dụng UTF-8 để có được sự kết hợp giữa không gian nhỏ và unicode?

+0

Microsoft SQL Server (ít nhất là 2000 và 2005) không hỗ trợ lưu trữ dữ liệu ký tự trong UTF-8. –

+0

Không phải là UTF-8 khá nhiều chỉ ASCII anyways? –

+0

Chỉ dành cho các điểm mã nằm trong phạm vi ASCII - nếu không nó hoàn toàn khác nhau –

27

Tôi muốn nói rằng vẫn còn những lý do hợp lệ để không sử dụng nvarchar.

  • Không gian lưu trữ là một bảo hiểm, chẳng hạn như trên một máy chủ chia sẻ hoặc cơ sở dữ liệu là thực sự khổng lồ.
  • Hiệu suất là rất quan trọng.
  • Phát triển Brownfield (tức là cơ sở dữ liệu có các bảng hiện có sử dụng varchar).
  • Bạn đang tích hợp với một hệ thống cũ hơn chỉ hiểu các ký tự byte đơn và/hoặc varchar.

Tuy nhiên, phát triển mới có lẽ nên sử dụng nvarchar esp. vì hệ thống 64 bit đang trở thành chuẩn mực. Ngoài ra, các công ty (thậm chí những công ty nhỏ) hiện nay phổ biến hơn trên toàn cầu.

+0

64 bit phải làm gì với nvarchar? – Jeremy

+2

ký tự 2 byte chiếm bộ nhớ gấp đôi, nhưng điều này ít quan tâm hơn đến các hệ thống 64 bit vì chúng có thể giải quyết nhiều RAM hơn các hệ thống 32 bit. 32-bit SQL Server trên Windows 32-bit (vẫn khá phổ biến trong '08) chỉ có thể sử dụng 2 GB RAM (nhảy qua hoops) –

2

Bộ nhớ ít tốn kém hơn bao giờ hết trong lịch sử, nhưng nếu bạn có thể lưu trữ nhiều gấp đôi dữ liệu trên một ổ đĩa cứng, điều đó thật hấp dẫn phải không?

Ngoài ra còn có RAM cho bộ nhớ đệm và ổ đĩa thể rắn, cả hai đều đắt hơn nhiều so với ổ đĩa cứng. Có ích khi sử dụng nhiều định dạng dữ liệu nhỏ hơn khi bạn có hàng triệu hàng.

3

Điểm 3 của bạn không hợp lệ. Các hệ thống được thiết kế chỉ cho một quốc gia sử dụng không phải lo lắng về unicode, và một số ngôn ngữ/sản phẩm đang sử dụng không hỗ trợ unicode ở tất cả hoặc chỉ một phần. Ví dụ: TurboTax chỉ dành cho Hoa Kỳ (và ngay cả với phiên bản Canada bằng tiếng Pháp vẫn chỉ là LATIN-1), vì vậy họ sẽ không cần hoặc phải lo lắng về unicode và có thể không hỗ trợ nó (tôi không biết họ có làm hay không, nhưng ngay cả khi họ làm, nó chỉ là một ví dụ).

"Ứng dụng ngày nay phải luôn tương thích với Unicode."

có lẽ là hợp lệ hơn thể hiện như:

" ứng dụng ngày nay nên luôn luôn Unicode tương thích nếu nhu cầu đặc biệt gì xảy ra để xử lý Unicode đúng cách, và một codebase tồn tại trước đó hoặc bất kỳ phần khác của ứng dụng không cần để được cập nhật đặc biệt để hỗ trợ nó"

+1

Tôi nghĩ rằng tôi sẽ luôn luôn cung cấp cho trọng lượng hơn đến nỗi đau của một nâng cấp tiềm năng để Unicode hơn là nỗi đau có lẽ sử dụng quá nhiều không gian lưu trữ. –

+0

@Edward, đó sẽ là một quyết định kinh doanh hơn là một quyết định kỹ thuật. Công ty chúng tôi (và nó là BIG) vẫn vận chuyển một số ứng dụng sử dụng cơ sở dữ liệu bằng tiếng Anh bởi vì đó là thị trường mong muốn của chúng tôi. – paxdiablo

+1

Là thành viên của quốc gia không nói tiếng Anh (có một số người trong số họ ra khỏi đó), nơi ngôn ngữ có chứa dấu phụ tôi có thể nói, các ứng dụng phải tương thích với Unicode. – PiRX

39

Point 4 không quan trọng bởi vì không gian lưu trữ là vô cùng tốn kém

nó không chỉ là lưu trữ, nhưng băng thông -. cp u, bộ nhớ, sao lưu, phục hồi, chuyển giao. Bảo tồn.

+0

Liên kết đến điều này trong câu trả lời của tôi ở đây: http://stackoverflow.com/questions/35366/varchar-vs-nvarchar-performance/198753#198753 – gbn

+0

Lưu trữ dưới dạng "NVARCHAR" trong cơ sở dữ liệu không có nghĩa là dữ liệu được gửi " trên dây "như mã hóa UCS-2 Unicode. Nó có thể đi qua dây và được đại diện trong bộ nhớ ứng dụng như UTF-8 ... mà là "một byte cho mỗi char hầu hết thời gian". –

2

Có cách nào để máy chủ cơ sở dữ liệu của bạn sử dụng UTF-8 làm mã hóa không? Sau đó bạn nhận được những lợi ích của lưu trữ thấp cho hầu hết các tải ASCII, và khả năng lưu trữ bất cứ điều gì trong phạm vi của Unicode để mở rộng là có thể.

Tôi cũng sẽ yêu cầu nhà cung cấp cơ sở dữ liệu của bạn hỗ trợ UTF-8 làm mã hóa cho loại SQL VARCHAR. Tôi không biết làm thế nào các máy chủ DB khác làm điều đó, nhưng tôi biết rằng bạn có thể sử dụng UTF-8 trong các lĩnh vực VARCHARTEXT trong ít nhất là MySQL và PostgreSQL. Tuy nhiên, tất cả những gì đã được nói, lý do duy nhất để không sử dụng trường mã hóa UTF-16 là nếu bạn phải tương tác với các ứng dụng sẽ phá vỡ đầu vào UTF-16. Đây sẽ là hầu hết các ứng dụng kế thừa được thiết kế để xử lý mã hóa văn bản ASCII hoặc ISO-8815, điều này sẽ tốt hơn khi xử lý UTF-8.

+0

Máy chủ MS SQL không hỗ trợ UTF8. Nó sử dụng UCS-2, tương đương với UTF-16 cho các ký tự trong mặt phẳng đa ngôn ngữ cơ bản (BMP). Tôi không biết nếu một hack tồn tại để có được nó để hỗ trợ UTF-8, nhưng tôi nghi ngờ nó. – Triynko

+0

Trong trường hợp đó, có thể tốt nhất nên bọc quyền truy cập vào cơ sở dữ liệu bằng bộ chuyển đổi ký tự để nó sẽ trả về giá trị UTF-8 cho ứng dụng và gửi giá trị UTF-16 tới cơ sở dữ liệu. Ít nhất, đó là những gì tôi sẽ làm nếu tôi đang làm việc với một hệ thống mà tôi phải lo lắng về ký tự mã hóa bản thân mình. Nếu bạn không phải lo lắng về việc mã hóa ký tự (ví dụ, Python 3 hoặc thứ gì đó chăm sóc nó một cách minh bạch) thì tôi cho rằng nó không thực sự quan trọng ... –

5

Như những người khác đã chỉ ra, nó không chỉ là chi phí lưu trữ.

Độ dài của cột sẽ ảnh hưởng đến số lượng hàng trên mỗi trang. Có ít hàng trên mỗi trang có nghĩa là ít hơn có thể vừa với bộ đệm của bạn, làm giảm hiệu suất. Tôi giả định rằng trong MSSQL, một cột NVARCHAR được lập chỉ mục sẽ sử dụng nhiều không gian hơn trong chỉ mục. Điều này có nghĩa là ít mục nhập chỉ mục hơn cho mỗi khối, do đó sẽ có nhiều khối hơn trong chỉ mục, do đó sẽ tìm kiếm khi quét (hoặc tìm kiếm) các chỉ mục, điều này cũng làm chậm truy cập được lập chỉ mục.

Vì vậy, nó mất hiệu suất của bạn trên mọi mặt trước. Nếu bạn thực sự không quan tâm (hoặc có thể đo lường hiệu suất và hạnh phúc với nó, tất nhiên), thì đó là tốt. Nhưng nếu bạn có một yêu cầu chính hãng để lưu trữ các ký tự unicode, tất nhiên, hãy sử dụng NVARCHAR.

Tôi có thể duy trì khả năng bảo trì bằng cách sử dụng NVARCHAR trong toàn bộ cơ sở dữ liệu của bạn vượt quá bất kỳ chi phí hiệu suất nào.

11

Tôi tin rằng so sánh nvarchars tốn kém hơn so với varchars nên nó hoàn toàn hợp lệ và thậm chí được ưu tiên ở những nơi bạn thực sự không cần khả năng unicode, tức là đối với một số ID nội bộ.

Và chi phí lưu trữ vẫn là không thành vấn đề. Nếu bạn có hàng tỷ hàng thì những khác biệt "nhỏ" này trở nên khá lớn.

5

Các loại câu hỏi này luôn có cùng một câu trả lời: phụ thuộc vào. Không có quy tắc phép thuật nào mà bạn nên theo dõi một cách mù quáng. Ngay cả việc sử dụng GOTO trong ngôn ngữ lập trình hiện đại có thể được biện minh: Is it ever advantageous to use 'goto' in a language that supports loops and functions? If so, why?

Vì vậy, câu trả lời là: sử dụng đầu và suy nghĩ về tình huống cụ thể. Trong trường hợp cụ thể này, hãy nhớ rằng bạn luôn có thể chuyển đổi từ varchar thành nvarchar trong cơ sở dữ liệu nếu nó chỉ ra yêu cầu của bạn thay đổi.

4

cột nvarchar Tôi đã thấy chuyển đổi sang varchar vì hai lý do:

  1. ứng dụng đang sử dụng MSSQL nhanh bản, trong đó có 4GB kích thước cơ sở dữ liệu hạn. Chuyển sang MSSQL Standard Phiên bản sẽ quá tốn kém nếu có nhiều triển khai cơ sở dữ liệu, cũng như trong các ứng dụng web một người thuê nhà hoặc các ứng dụng có DBMS được nhúng. Phiên bản web SQL2008 rẻ hơn có thể trợ giúp tại đây.

  2. nvarchar (4000) không đủ nhưng bạn không muốn cột ntext. Vì vậy, bạn chuyển đổi thành varchar (8000). Tuy nhiên, trong hầu hết các trường hợp, bạn có thể nên chuyển đổi thành nvarchar (tối đa).

18

Bạn nên chọn VARCHAR trên NVARCHAR cho nhiều loại cột khác nhau và lựa chọn sẽ dựa trên cơ sở mỗi cột.

cột điển hình đó sẽ không yêu cầu thêm các gánh chịu NVARCHAR overhead sẽ là:

cột ID-type: tấm giấy phép, SSN, định danh Chart Bệnh nhân, vv

cột Code: mã tiền tệ quốc tế (USD, UKP, vv), mã quốc gia ISO (Hoa Kỳ, Vương quốc Anh, v.v.), Mã ngôn ngữ (en-us, v.v.), mã phân đoạn kế toán, v.v.

Cột mã và mã zip.

1

Tôi đã thấy một số cơ sở dữ liệu nơi các chỉ mục (chỉ mục? ... các cuộc tranh luận khác nhau) đã lớn hơn dữ liệu. Nếu người ta có thể lấy đi một nửa nhu cầu lưu trữ (varchar) trong chỉ mục thì giả sử rằng tương đương với gấp đôi mật độ truy cập của một trang nhất định và tính hiệu quả lấp đầy hơn dẫn đến yêu cầu lưu trữ ít hơn/ghi/khóa & ít hơn đã được đề cập).

1

Nghiêng của tôi là "sử dụng NVARCHAR" làm mặc định ... nhưng @CadeRoux có một điểm tốt: nếu bạn chắc chắn dữ liệu sẽ không bao giờ giữ bất kỳ thứ gì ngoài ASCII - như biển số xe của Mỹ - VARCHAR có thể giúp bạn tiết kiệm một chút chi phí.

Tôi muốn nói mặt trái của tuyên bố tốt của ông là "DO use NVARCHAR" cho bất kỳ thứ gì có tên (người, đường phố, địa điểm) hoặc văn bản ngôn ngữ tự nhiên (email, trò chuyện, bài viết, bài đăng trên blog, chú thích ảnh). Nếu không, cột "firstname" của bạn sẽ không thể mã hóa chính xác "François" hoặc "José" và các cột văn bản của bạn sẽ không cho phép văn bản có dấu phụ "nước ngoài" hoặc - cho vấn đề đó - các ký tự rất phổ biến ở Hoa Kỳ như dấu "¢", dấu phân đoạn "¶", dấu đầu dòng "•".(Vì không ai trong số đó là các ký tự ASCII và không có cách nào tốt, tiêu chuẩn để đưa chúng vào một trường VARCHAR. Hãy tin tôi đi: bạn sẽ tự làm tổn thương bản thân.)

BẤT CỨ dự án tôi đã làm việc trên , Tôi đã không bao giờ bị mắng vì đã sử dụng NVARCHAR vì tôi đã "lãng phí quá nhiều tiền của công ty vào không gian đĩa". Và nếu tôi phải làm lại mã hoặc lược đồ DB (đặc biệt là trên một hệ thống sản xuất trực tiếp), chi phí được chi tiêu lại sẽ DỄ DÀNG lớn hơn "tiết kiệm" khi mua một đĩa nhỏ hơn 50%.

Để thực sự hiểu câu hỏi này, bạn thực sự phải hiểu các mã hóa điển hình của ASCII, Unicode và Unicode (như UCS-2 và UTF-8).

+0

Một NVARCHAR (12) sẽ mất 24 byte và có thể chứa 12 ký tự trong BMP hoặc 6 ký tự bên ngoài. Một VARCHAR 8 bit (24), được sử dụng với các phương thức truy cập phù hợp, có thể chứa 24 ký tự ASCII, 12 ký tự ở phần thấp nhất của BMP, bất kỳ 8 trong BMP, hoặc bất kỳ 6 bên ngoài BMP; cách khác, nó có thể được sử dụng để giữ bất kỳ kết hợp nào của 8 ký tự bằng cách sử dụng mã hóa lưu trữ 3 byte cho mỗi ký tự, ví dụ: với MSB được đặt trên byte đầu tiên của mỗi bộ ba bộ và xóa trên hai bộ kia. – supercat

Các vấn đề liên quan