Sự khác biệt hiệu suất chính giữa các loại dữ liệu SQL Server varchar và nvarchar là gì?


236

Tôi đang làm việc trên một cơ sở dữ liệu cho một ứng dụng web nhỏ ở trường tôi đang sử dụng SQL Server 2005.
Tôi thấy một vài trường phái suy nghĩ về vấn đề varcharvs nvarchar:

  1. Sử dụng varchartrừ khi bạn xử lý nhiều dữ liệu quốc tế, sau đó sử dụng nvarchar.
  2. Chỉ cần sử dụng nvarcharcho tất cả mọi thứ.

Tôi bắt đầu thấy được ưu điểm của chế độ xem 2. Tôi biết rằng nvarchar chiếm không gian gấp đôi, nhưng đó không hẳn là một vấn đề lớn vì điều này sẽ chỉ lưu trữ dữ liệu cho vài trăm sinh viên. Đối với tôi có vẻ như sẽ không dễ dàng nhất để không lo lắng về điều đó và chỉ cho phép mọi thứ sử dụng nvarchar. Hay là tôi đang thiếu thứ gì đó?


câu hỏi tương tự ở đây: stackoverflow.com/questions/312170/ ED EDIT của le dorfier: điều thú vị đã đi đến kết luận hoàn toàn ngược lại.
Cậu bé Booji

6
tham khảo chủ đề rộng rãi hơn nhiều mà đi đến kết luận ngược lại. stackoverflow.com/questions/312170/
Mạnh

2
Jason: Tôi hy vọng đây không phải là một yêu cầu không phù hợp, nhưng bạn có thể vui lòng xem xét việc thay đổi câu trả lời được chấp nhận thành gbn's không . Câu trả lời của JoeBarone là sai lầm khủng khiếp vì nhiều lý do. Có nó được "chấp nhận" đánh lừa người mới để đưa ra lựa chọn xấu. Việc "luôn luôn sử dụng NVARCHAR" là không cần thiết và lãng phí , và nó có thể có tác động rất xấu đến hiệu suất và chi phí / ngân sách phần cứng. Một vài hàng, thậm chí vài nghìn, sẽ không thành vấn đề. Nhưng các hệ thống phát triển nhanh hơn mọi người mong đợi, vì vậy câu trả lời được chấp nhận hiện tại là một sự bất đồng cho cộng đồng. Cảm ơn bạn.
Solomon Rutzky

Câu trả lời:


140

Luôn luôn sử dụng nvarchar.

Bạn có thể không bao giờ cần các ký tự hai byte cho hầu hết các ứng dụng. Tuy nhiên, nếu bạn cần hỗ trợ các ngôn ngữ hai byte và bạn chỉ có hỗ trợ một byte trong lược đồ cơ sở dữ liệu của mình thì thực sự tốn kém để quay lại và sửa đổi trong toàn bộ ứng dụng của bạn.

Chi phí di chuyển một ứng dụng từ varchar sang nvarchar sẽ nhiều hơn một chút dung lượng đĩa phụ bạn sẽ sử dụng trong hầu hết các ứng dụng.


4
Việc quay lại và thêm hỗ trợ cho văn bản / tin nhắn đa ngôn ngữ, múi giờ, đơn vị đo lường và tiền tệ là rất khó khăn, vì vậy mọi người PHẢI luôn mã hóa những thứ này trong ứng dụng của họ từ ngày đầu tiên, LUÔN LUÔN (ngay cả khi nó chỉ có trên trang chủ của bạn ứng dụng)!
KM.

82
Điều gì về kích thước chỉ mục, sử dụng bộ nhớ, vv? Tôi giả sử bạn luôn sử dụng int khi bạn có thể sử dụng tinyint quá "chỉ trong trường hợp"?
gbn

99
Luôn luôn mã hóa / lập kế hoạch cho một trang web đa ngôn ngữ (khi bạn không có ý kiến ​​trái chiều rằng bạn sẽ cần nó) giống như nói với tất cả những người trẻ tuổi họ nên mua một chiếc SUV cỡ lớn 8 chỗ ngồi cho chiếc xe đầu tiên của họ ... sau tất cả , họ có thể kết hôn một ngày nào đó và có thể có 6 đứa con. Tôi thà tận hưởng hiệu suất và hiệu quả trong khi tôi có thể và trả giá cho việc nâng cấp khi / nếu tôi cần.
EJ Brennan

4
@cbmeek: Tôi không mã cho những gì tôi không biết. Nhưng nếu bạn có thể sử dụng nó mà không có hiệu suất đáng chú ý, thì cơ sở dữ liệu của bạn không đủ lớn để nó có vấn đề ...
gbn

60
Thông thường khi mọi người bắt đầu câu trả lời của họ bằng từ "Luôn luôn" thì bạn nên bỏ qua mọi thứ xuất hiện sau đó. (Lưu ý rằng tôi đã bắt đầu câu nói đó bằng từ "thường" :)
Brandon Moore

226

Dung lượng ổ đĩa không phải là vấn đề ... nhưng bộ nhớ và hiệu suất sẽ có. Nhân đôi số lần đọc trang, gấp đôi kích thước chỉ mục, THÍCH lạ và = hành vi không đổi, v.v.

Bạn có cần lưu trữ tập lệnh tiếng Trung vv? Có hay không...

Và từ MS BOL " Hiệu ứng lưu trữ và hiệu suất của Unicode "

Chỉnh sửa :

Câu hỏi SO gần đây nhấn mạnh hiệu suất của nvarchar có thể ...

SQL Server sử dụng CPU cao khi tìm kiếm bên trong chuỗi nvarchar


19
+1, nếu ứng dụng của bạn đi quốc tế, bạn sẽ có nhiều vấn đề khác phải lo lắng về việc tìm kiếm / thay thế cho nvarchar: văn bản / tin nhắn đa ngôn ngữ, múi giờ, đơn vị đo lường và tiền tệ
KM.

2
Nhưng điều gì sẽ xảy ra nếu đôi khi bạn cần lưu trữ một tên nước ngoài, như José hoặc Bjørn?
Qwertie

7
@Qwertie: sau đó bạn sử dụng nvarchar. Những gì bạn không làm nó sử dụng nó một cách không cần thiết. Dù sao thì hai cái tên đó cũng phù hợp với varchar IIRC
gbn

6
Nói dung lượng đĩa không phải là vấn đề không đúng với mọi người. Chúng tôi đã ngây thơ sử dụng nvarchar một cách không cần thiết trong một ứng dụng ngân hàng lớn với hàng tỷ hồ sơ được lưu trữ trong nhiều năm. Với bộ lưu trữ dựa trên SAN đắt tiền với nhân rộng, sao lưu và khắc phục thảm họa, điều này thực sự có thể chuyển thành hàng triệu đô la chi phí cho nvarchar so với varchar. Chưa kể có một tác động hiệu suất lớn (100%) để phải đọc gấp đôi số byte từ đĩa cho mỗi lần đọc.
codemonkey

2
@codemonkey, et al: Tôi đã làm những gì có thể để giải quyết vấn đề lãng phí không gian một cách toàn diện trong bài viết sau: Đĩa có giá rẻ! ORLY? (đăng ký miễn phí là cần thiết, mặc dù). Bài viết này nhằm giúp ngăn chặn tình huống mà codemonkey gặp phải liên quan đến việc lưu trữ cấp doanh nghiệp, đắt tiền.
Solomon Rutzky

59

Hãy kiên định! THAM GIA một VARCHAR để NVARCHAR có một thành tích lớn.


115
Nếu bạn đang tham gia vào các trường ký tự thì cơ sở dữ liệu của bạn có thể có vấn đề tồi tệ hơn so với việc sử dụng nvarchar hay varchar, nói chung.
Brandon Moore

@Thomas Harlan Một xét nghiệm đơn giản chứng minh với tôi rằng không có sự khác biệt hữu hình giữa tham gia nvarcharđể varcharvs chuyển nvarcharđến varcharvà tham gia vào varchar. Tất nhiên trừ khi bạn có nghĩa là nhất quán trong các kiểu dữ liệu cột, không tham gia.
ajeh

1
@ajeh và Thomas: 1) Các xét nghiệm "đơn giản" thường gây hiểu nhầm vì chúng không bao gồm các biến thể gây ra sự khác biệt trong hành vi. 2) Nếu người ta thấy hiệu suất mạnh mẽ khi trộn VARCHARNVARCHARđó là do lập chỉ mục của VARCHARcột cùng với loại Collation được sử dụng cho cột đó (và do đó là chỉ mục). Tôi đề cập chi tiết chủ đề này trong bài đăng trên blog sau: Tác động đến các Chỉ mục khi Trộn các loại VARCHAR và NVARCHAR .
Solomon Rutzky

44

nvarchar sẽ có chi phí đáng kể trong bộ nhớ, lưu trữ, thiết lập và lập chỉ mục, vì vậy nếu thông số kỹ thuật cho rằng nó thực sự sẽ không bao giờ cần thiết, đừng bận tâm.

Tôi sẽ không có quy tắc "luôn luôn nvarchar" cứng và nhanh vì nó có thể là một sự lãng phí hoàn toàn trong nhiều tình huống - đặc biệt là ETL từ ASCII / EBCDIC hoặc các mã định danh và cột mã thường là khóa và khóa ngoại.

Mặt khác, có rất nhiều trường hợp cột, trong đó tôi chắc chắn sẽ hỏi câu hỏi này sớm và nếu tôi không nhận được câu trả lời khó và nhanh ngay lập tức, tôi sẽ tạo cột nvarchar.


26

Tôi ngần ngại để thêm một câu trả lời khác ở đây vì đã có khá nhiều, nhưng một vài điểm cần được thực hiện mà chưa được thực hiện hoặc không được thực hiện rõ ràng.

Thứ nhất: Không phải lúc nào cũng sử dụng NVARCHAR. Đó là một thái độ / cách tiếp cận rất nguy hiểm và thường tốn kém. Và không có gì tốt hơn để nói " Không bao giờ sử dụng con trỏ" vì đôi khi chúng là phương tiện hiệu quả nhất để giải quyết một vấn đề cụ thể, và công việc chung của việc thực hiện một WHILEvòng lặp sẽ hầu như luôn chậm hơn so với Con trỏ được thực hiện đúng .

Lần duy nhất bạn nên sử dụng thuật ngữ "luôn luôn" là khi khuyên "luôn luôn làm những gì tốt nhất cho tình huống". Được cho là thường rất khó xác định, đặc biệt là khi cố gắng cân bằng lợi ích ngắn hạn trong thời gian phát triển (người quản lý: "chúng tôi cần tính năng này - mà bạn chưa biết đến cho đến tận bây giờ - một tuần trước!") -Chi phí bảo trì (người quản lý ban đầu gây áp lực cho nhóm để hoàn thành dự án 3 tháng trong giai đoạn nước rút 3 tuần: "tại sao chúng ta gặp phải những vấn đề về hiệu suất này? Làm thế nào chúng ta có thể thực hiện X mà không linh hoạt? chạy nước rút hoặc hai lần để khắc phục điều này. Chúng ta có thể làm gì trong một tuần để có thể quay lại các mục ưu tiên của mình? Và chúng ta chắc chắn cần dành nhiều thời gian hơn cho thiết kế để điều này không xảy ra! ").

Thứ hai: Câu trả lời của @ gbn chạm vào một số điểm rất quan trọng cần xem xét khi đưa ra quyết định mô hình hóa dữ liệu nhất định khi đường dẫn không rõ ràng 100%. Nhưng thậm chí còn nhiều hơn để xem xét:

  • kích thước của tệp nhật ký giao dịch
  • cần có thời gian để nhân rộng (nếu sử dụng nhân rộng)
  • cần có thời gian để ETL (nếu ETLing)
  • cần có thời gian để chuyển nhật ký đến một hệ thống từ xa và khôi phục (nếu sử dụng Nhật ký vận chuyển)
  • kích thước của bản sao lưu
  • thời gian cần thiết để hoàn thành sao lưu
  • thời gian cần thiết để khôi phục (điều này có thể quan trọng vào một ngày nào đó ;-)
  • kích thước cần thiết cho tempdb
  • hiệu suất của các kích hoạt (đối với các bảng được chèn và xóa được lưu trữ trong tempdb)
  • hiệu suất của phiên bản hàng (nếu sử dụng SNAPSHOT ISOLATION, vì kho phiên bản nằm trong tempdb)
  • khả năng có được dung lượng đĩa mới khi CFO nói rằng họ chỉ chi 1 triệu đô la cho SAN năm ngoái và vì vậy họ sẽ không ủy quyền thêm 250 nghìn đô la nữa cho bộ nhớ bổ sung
  • khoảng thời gian cần thiết để thực hiện các thao tác INSERT và UPDATE
  • thời gian cần thiết để bảo trì chỉ số
  • v.v.

Không gian lãng phí có hiệu ứng tầng lớn trên toàn bộ hệ thống. Tôi đã viết một bài viết đi sâu vào chi tiết rõ ràng về chủ đề này: Đĩa là giá rẻ! ORLY? (yêu cầu đăng ký miễn phí; xin lỗi tôi không kiểm soát chính sách đó).

Thứ ba: Mặc dù một số câu trả lời tập trung không chính xác vào khía cạnh "đây là một ứng dụng nhỏ" và một số câu trả lời chính xác là "sử dụng những gì phù hợp", không có câu trả lời nào cung cấp hướng dẫn thực sự cho OP Một chi tiết quan trọng được đề cập trong Câu hỏi đây có phải là một trang web cho trường học của họ Tuyệt quá! Vì vậy, chúng tôi có thể đề nghị rằng:

  • Các lĩnh vực cho tên sinh viên và / hoặc Khoa có lẽ nên NVARCHARvì, theo thời gian, chỉ có nhiều khả năng tên từ các nền văn hóa khác sẽ xuất hiện ở những nơi đó.
  • Nhưng đối với địa chỉ đường phố và tên thành phố? Mục đích của ứng dụng không được nêu rõ (nó sẽ hữu ích) nhưng giả sử các bản ghi địa chỉ, nếu có, chỉ liên quan đến một khu vực địa lý cụ thể (nghĩa là một ngôn ngữ / văn hóa), sau đó sử dụngVARCHAR với Trang Mã thích hợp (mà được xác định từ Collation của trường).
  • Nếu lưu trữ mã ISO của Bang và / hoặc Quốc gia (không cần lưu trữ INT/ TINYINTvì mã ISO có độ dài cố định, con người có thể đọc được và tốt, tiêu chuẩn :) sử dụng CHAR(2)cho hai mã chữ cái và CHAR(3)nếu sử dụng 3 mã chữ cái. Và xem xét sử dụng Collation nhị phân như Latin1_General_100_BIN2.
  • Nếu lưu trữ mã bưu chính (ví dụ mã zip), hãy sử dụng VARCHARvì đó là tiêu chuẩn quốc tế để không bao giờ sử dụng bất kỳ chữ cái nào ngoài AZ. Và có, vẫn sử dụng VARCHARngay cả khi chỉ lưu trữ mã zip của Hoa Kỳ chứ không phải INT vì mã zip không phải là số, chúng là chuỗi và một số trong số chúng có số "0" hàng đầu. Và xem xét sử dụng Collation nhị phân như Latin1_General_100_BIN2.
  • Nếu lưu trữ địa chỉ email và / hoặc URL, hãy sử dụng NVARCHARvì cả hai địa chỉ này hiện có thể chứa các ký tự Unicode.
  • và như thế....

Thứ tư: Bây giờ bạn có NVARCHARdữ liệu chiếm gấp đôi dung lượng cần thiết cho dữ liệu vừa vặn VARCHAR("vừa vặn" = không biến thành "?") Và bằng cách nào đó, như thể bằng phép thuật, ứng dụng đã phát triển và hiện có hàng triệu bản ghi trong ít nhất một trong các trường trong đó hầu hết các hàng là ASCII tiêu chuẩn nhưng một số có chứa các ký tự Unicode để bạn phải giữ NVARCHAR, hãy xem xét các điều sau:

  1. Nếu bạn đang sử dụng SQL Server 2008 - 2016 RTM đang ở Phiên bản doanh nghiệp, HOẶC nếu sử dụng SQL Server 2016 SP1 (giúp nén dữ liệu có sẵn trong tất cả các phiên bản) hoặc mới hơn, thì bạn có thể bật Nén dữ liệu . Nén dữ liệu có thể (nhưng sẽ không "luôn luôn") nén dữ liệu Unicode trong NCHARNVARCHARcác trường. Các yếu tố quyết định là:

    1. NCHAR(1 - 4000)NVARCHAR(1 - 4000)sử dụng Lược đồ nén tiêu chuẩn cho Unicode , nhưng chỉ bắt đầu trong SQL Server 2008 R2, và chỉ cho dữ liệu IN ROW, chứ không phải QUÁ LỚN! Điều này dường như tốt hơn thuật toán nén ROW / PAGE thông thường.
    2. NVARCHAR(MAX)XML(và tôi cũng đoán VARBINARY(MAX), TEXTNTEXT) dữ liệu đó là TRÊN ROW (không tắt hàng trong LOB hoặc OVERFLOW trang) ít nhất có thể TRANG nén, nhưng không Row nén. Tất nhiên, nén PAGE phụ thuộc vào kích thước của giá trị liên tiếp: Tôi đã thử nghiệm với VARCHAR (MAX) và thấy rằng hàng 6000 ký tự / byte sẽ không nén, nhưng hàng 4000 ký tự / byte đã làm.
    3. Bất kỳ dữ liệu ROW TẮT, LOB hoặc QUÁ LỚN = Không nén cho bạn!
  2. Nếu sử dụng SQL Server 2005 hoặc 2008 - 2016 RTM và không phải trên Phiên bản doanh nghiệp, bạn có thể có hai trường: một VARCHARvà một NVARCHAR. Ví dụ: giả sử bạn đang lưu trữ các URL chủ yếu là tất cả các ký tự ASCII cơ bản (giá trị 0 - 127) và do đó phù hợp với VARCHAR, nhưng đôi khi có các ký tự Unicode. Lược đồ của bạn có thể bao gồm 3 trường sau:

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );

    Trong mô hình này, bạn chỉ CHỌN từ [URL]cột được tính toán. Để chèn và cập nhật, bạn xác định trường nào sẽ sử dụng bằng cách xem nếu chuyển đổi có làm thay đổi giá trị đến hay không, phải là NVARCHARloại:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
  3. Bạn có thể GZIP các giá trị đến vào VARBINARY(MAX)và sau đó giải nén trên đường ra:

    • Đối với SQL Server 2005 - 2014: bạn có thể sử dụng SQLCLR. SQL # (thư viện SQLCLR mà tôi đã viết) đi kèm với Util_GZipUtil_GUnzip trong phiên bản miễn phí
    • Đối với SQL Server 2016 trở lên: bạn có thể sử dụng các hàm COMPRESSDECOMPRESShàm tích hợp, cũng là GZip.
  4. Nếu sử dụng SQL Server 2017 hoặc mới hơn, bạn có thể xem xét việc tạo bảng thành Chỉ mục cột phân cụm.

  5. Mặc dù đây chưa phải là một tùy chọn khả thi, SQL Server 2019 giới thiệu hỗ trợ riêng cho UTF-8 in VARCHAR/ CHARdatatypes. Hiện tại có quá nhiều lỗi với nó để sử dụng, nhưng nếu chúng đã được sửa, thì đây là một tùy chọn cho một số tình huống. Vui lòng xem bài đăng của tôi, " Hỗ trợ UTF-8 bản địa trong SQL Server 2019: Tiên tri cứu rỗi hay sai? ", Để biết phân tích chi tiết về tính năng mới này.


7
Vỗ tay chậm. Đơn giản là ngạc nhiên khi "luôn luôn sử dụng nvarchar" đã nhận được 140 phiếu bầu và điều này thì không. Công việc tuyệt vời trên bài đăng này.
schizoid04

1
@ schizoid04 Cảm ơn. Công bằng mà nói, câu trả lời được chấp nhận đã được đăng 7 năm trước tôi, vì vậy có rất nhiều lưu lượng truy cập đã bình chọn trên đó (và / hoặc nhiều người khác) không bao giờ quay lại để đánh giá lại. Tuy nhiên, nó cung cấp một điểm đối lập rất chắc chắn với lý thuyết "sự khôn ngoan của đám đông" thúc đẩy các diễn đàn dựa trên phiếu bầu. Có quá nhiều thông tin sai lệch ngoài kia. Ví dụ: điều này trên DBA.SE. Câu trả lời khác, được chấp nhận trước khi tôi đăng bài của tôi, là "chính xác" bởi các định nghĩa hẹp nhất, gây hiểu lầm và chứa thông tin mà tôi không đồng ý với tôi, nhưng nó vẫn vượt xa tôi.
Solomon Rutzky

22

Đối với ứng dụng của bạn, nvarchar vẫn ổn vì kích thước cơ sở dữ liệu nhỏ. Nói "luôn luôn sử dụng nvarchar" là một sự đơn giản hóa quá lớn. Nếu bạn không bắt buộc phải lưu trữ những thứ như Kanji hoặc các nhân vật điên rồ khác, hãy sử dụng VARCHAR, nó sẽ sử dụng ít không gian hơn. Người tiền nhiệm của tôi trong công việc hiện tại của tôi đã thiết kế một cái gì đó bằng cách sử dụng NVARCHAR khi không cần thiết. Gần đây chúng tôi đã chuyển nó sang VARCHAR và chỉ lưu 15 GB trên bảng đó (nó được viết rất cao). Hơn nữa, nếu sau đó bạn có một chỉ mục trên bảng đó và bạn muốn bao gồm cột đó hoặc tạo một chỉ mục tổng hợp, bạn vừa làm cho kích thước tệp chỉ mục của mình lớn hơn.

Chỉ cần chu đáo trong quyết định của bạn; trong phát triển SQL và định nghĩa dữ liệu dường như hiếm khi có một "câu trả lời mặc định" (tất nhiên ngoài việc tránh các con trỏ bằng mọi giá).


10

Vì ứng dụng của bạn nhỏ, về cơ bản không có sự gia tăng chi phí đáng kể nào khi sử dụng nvarchar trên varchar và bạn sẽ tự cứu mình khỏi những cơn đau đầu tiềm ẩn nếu bạn có nhu cầu lưu trữ dữ liệu unicode.


8

Nói chung; Bắt đầu với kiểu dữ liệu đắt nhất có ít ràng buộc nhất. Đưa nó vào sản xuất . Nếu hiệu suất bắt đầu là một vấn đề, hãy tìm hiểu những gì thực sự được lưu trữ trong các nvarcharcột đó. Có nhân vật nào trong đó không phù hợp varchar? Nếu không, chuyển sang varchar. Đừng cố tối ưu hóa trước khi bạn biết đau ở đâu. Tôi đoán là sự lựa chọn giữa nvarchar / varchar không phải là điều sẽ làm chậm ứng dụng của bạn trong tương lai gần. Sẽ có các phần khác của ứng dụng, nơi điều chỉnh hiệu suất sẽ mang lại cho bạn nhiều tiền hơn cho các đô la .


7

Trong vài năm qua, tất cả các dự án của chúng tôi đã sử dụng NVARCHAR cho mọi thứ, vì tất cả các dự án này đều là đa ngôn ngữ. Dữ liệu được nhập từ các nguồn bên ngoài (ví dụ: tệp ASCII, v.v.) được chuyển đổi thành Unicode trước khi đưa vào cơ sở dữ liệu.

Tôi chưa gặp phải bất kỳ vấn đề nào liên quan đến hiệu suất từ ​​các chỉ mục lớn hơn, v.v. Các chỉ mục sử dụng nhiều bộ nhớ hơn, nhưng bộ nhớ thì rẻ.

Cho dù bạn sử dụng các thủ tục được lưu trữ hay xây dựng SQL một cách nhanh chóng, hãy đảm bảo rằng tất cả các hằng chuỗi đều có tiền tố là N (ví dụ: SET @foo = N'Hello world. ';) Vì vậy hằng số cũng là Unicode. Điều này tránh bất kỳ chuyển đổi loại chuỗi trong thời gian chạy.

YMMV.


4
Bạn có thể không có vài trăm triệu bản ghi trong các bảng bạn đang làm việc. Tôi đồng ý rằng đối với hầu hết các ứng dụng mặc định cho nvarchar là tốt, nhưng không phải tất cả.
Brandon Moore

7

Tôi có thể nói từ kinh nghiệm về điều này, hãy cẩn thận nvarchar. Trừ khi bạn hoàn toàn yêu cầu nó loại trường dữ liệu này sẽ phá hủy hiệu suất trên cơ sở dữ liệu lớn hơn. Tôi được thừa hưởng một cơ sở dữ liệu gây tổn hại về hiệu suất và không gian. Chúng tôi đã có thể giảm 70% cơ sở dữ liệu về kích thước! Có một số sửa đổi khác được thực hiện để giúp thực hiện nhưng tôi chắc chắn rằng điều varcharđó cũng giúp ích đáng kể cho điều đó. Nếu cơ sở dữ liệu của bạn có tiềm năng phát triển bảng lên tới một triệu + hồ sơ, hãy tránh xa nvarcharbằng mọi giá.


4

Tôi thường xuyên giải quyết câu hỏi này tại nơi làm việc:

  • Nguồn cấp dữ liệu FTP của hàng tồn kho và giá cả - Mô tả mục và văn bản khác ở dạng nvarchar khi varchar hoạt động tốt. Chuyển đổi chúng thành varchar giảm kích thước tệp gần một nửa và thực sự hữu ích với việc tải lên.

  • Kịch bản trên hoạt động tốt cho đến khi ai đó đưa một ký tự đặc biệt vào mô tả vật phẩm (có thể là nhãn hiệu, không thể nhớ)

Tôi vẫn không sử dụng nvarchar mỗi lần qua varchar. Nếu có bất kỳ nghi ngờ hoặc tiềm năng nào cho các ký tự đặc biệt, tôi sử dụng nvarchar. Tôi thấy tôi sử dụng varchar chủ yếu khi tôi kiểm soát 100% những gì đang chiếm lĩnh lĩnh vực này.


3

Tại sao, trong tất cả các cuộc thảo luận này, không có đề cập đến UTF-8? Có thể lưu trữ toàn bộ ký tự unicode không có nghĩa là người ta phải luôn phân bổ hai byte cho mỗi ký tự (hoặc "điểm mã" để sử dụng thuật ngữ UNICODE). Tất cả ASCII là UTF-8. SQL Server có kiểm tra các trường VARCHAR () rằng văn bản có nghiêm ngặt ASCII (tức là bit byte trên cùng không) không? Tôi hy vọng không.

Nếu sau đó bạn muốn lưu trữ unicode muốn tương thích với các ứng dụng chỉ ASCII cũ hơn, tôi nghĩ rằng sử dụng VARCHAR () và UTF-8 sẽ là viên đạn ma thuật: Nó chỉ sử dụng nhiều không gian hơn khi cần.

Đối với những người bạn không quen thuộc với UTF-8, tôi có thể đề xuất một mồi .


2
Những gì bạn đang đề xuất có thể hoạt động cho một số ứng dụng, nhưng người ta cũng phải xem xét tác động của lớp mã hóa bổ sung đối với cách xử lý văn bản SQL. Cụ thể, các đối chiếu, tìm kiếm và khớp mẫu sẽ được thực hiện. Và nếu các báo cáo được chạy dựa trên cơ sở dữ liệu, các công cụ báo cáo tiêu chuẩn sẽ không xen kẽ các ký tự nhiều byte một cách chính xác. Và nhập khẩu số lượng lớn và xuất khẩu có thể được thực hiện. Tôi nghĩ rằng, trong suốt thời gian dài, chương trình này có thể gặp nhiều rắc rối hơn giá trị của nó.
Jeffrey L Whitledge

1
Không thể lưu trữ UTF-8 trong các cột VARCHAR. MSSQL sẽ luôn chuyển đổi dữ liệu UTF-8 của bạn sang đối chiếu cột. Nếu bạn làm hỏng việc đối chiếu (như cố gắng lưu trữ CP1252 bằng tiếng Latin_1), chuyển đổi sẽ không hoạt động và bạn sẽ kết thúc với các byte bổ sung trong dữ liệu của mình. Nó có vẻ hoạt động tốt khi bạn chuyển đổi latin_1 thành UTF-8 (ở phía ứng dụng) và trở lại thành latin_1 (phía db) nhưng đó chỉ là ảo ảnh. Bạn có thể lén theo DB tự động chuyển đổi sang đối chiếu cột của bạn bằng cách sử dụng freetds và đặt giao thức thành một cái gì đó nhỏ hơn 7, nhưng bạn mất khả năng truy vấn nvarchar.
chugadie

1
@chugadie và Tevya: câu trả lời này hơi vô lý. SQL Server chỉ sử dụng UCS-2 / UTF-16 để lưu trữ dữ liệu Unicode (tức là các loại XML và N-prefixed). Bạn không có lựa chọn sử dụng UTF-8. Ngoài ra, mã hóa Unicode (UTF-8, UCS-2 / UTF-16 và UTF-32) không thể được áp dụng cho các trường VARCHAR.
Solomon Rutzky

2

Sẽ có những trường hợp đặc biệt khi bạn muốn cố tình hạn chế loại dữ liệu để đảm bảo nó không chứa các ký tự từ một bộ nhất định. Ví dụ, tôi có một kịch bản mà tôi cần lưu trữ tên miền trong cơ sở dữ liệu. Quốc tế hóa cho các tên miền không đáng tin cậy vào thời điểm đó vì vậy tốt hơn là hạn chế đầu vào ở cấp cơ sở và giúp tránh mọi vấn đề tiềm ẩn.


1

Nếu bạn đang sử dụng NVARCHARchỉ vì một thủ tục lưu trữ hệ thống yêu cầu, sự xuất hiện thường xuyên nhất là hiểu sao sp_executesql, và SQL động của bạn là rất dài, bạn sẽ khấm khá hơn từ góc độ hiệu suất làm tất cả thao tác chuỗi (nối, thay thế, vv) trong VARCHARsau đó chuyển đổi kết quả cuối cùng NVARCHARvà đưa nó vào tham số Proc. Vì vậy, không phải lúc nào cũng sử dụng NVARCHAR!

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.