ما هي أهم الاختلافات الأداء بين varchar و nvarchar البيانات SQL Server أنواع ؟

StackOverflow https://stackoverflow.com/questions/35366

سؤال

انا اعمل على قاعدة بيانات صغيرة التطبيق على شبكة الإنترنت في المدرسة باستخدام SQL Server 2005.
أرى عددا من مدارس الفكر في مسألة varchar مقابل nvarchar:

  1. استخدام varchar إلا إذا كنت تتعامل مع الكثير من البيانات المدولة ، ثم استخدام nvarchar.
  2. مجرد استخدام nvarchar لكل شيء.

أنا بدأت لمعرفة مزايا عرض 2.وأنا أعلم أن nvarchar لا يستغرق أكثر من ضعفي مساحة, ولكن هذا ليس بالضرورة صفقة ضخمة لأن هذا لن يؤدي إلا إلى تخزين البيانات على بضع مئات من الطلاب.بالنسبة لي يبدو أنه سيكون من الأسهل أن لا تقلق بشأن ذلك فقط يسمح كل شيء إلى استخدام nvarchar.أو هل هناك شيء أنا في عداد المفقودين ؟

هل كانت مفيدة؟

المحلول

دائما استخدام nvarchar.

قد لا تحتاج إلى الأحرف مزدوجة البايت بالنسبة لمعظم التطبيقات.ومع ذلك, إذا كنت بحاجة إلى دعم مزدوجة البايت لغات لديك فقط بايت واحد في مخطط قاعدة البيانات انها مكلفة حقا إلى العودة وتعديل جميع أنحاء التطبيق الخاص بك.

تكلفة ترحيل تطبيق واحد من varchar إلى nvarchar سوف تكون أكثر بكثير من المزيد من مساحة القرص سوف تستخدم في معظم التطبيقات.

نصائح أخرى

مساحة القرص ليس هو القضية...ولكن الذاكرة و الأداء.ضعف صفحة يقرأ مزدوج مؤشر حجم غريبة مثل = ثابت السلوك وما إلى ذلك

هل تحتاج إلى المتجر الصيني وما إلى ذلك السيناريو ؟ نعم أو لا...

و من مايكروسوفت بول "التخزين والأداء آثار Unicode"

تحرير:

الأخيرة حتى السؤال تسليط الضوء على مدى سوء nvarchar الأداء يمكن أن يكون...

SQL Server يستخدم وحدة المعالجة المركزية عالية عند البحث داخل nvarchar سلاسل

تكون متسقة!الانضمام جي VARCHAR إلى NVARCHAR كبير ضرب الأداء.

nvarchar سوف يكون حمل كبير في الذاكرة والتخزين مجموعة العمل والفهرسة ، حتى إذا المواصفات تملي أنه حقا سوف أبدا يكون من الضروري, لا تهتم.

لن يكون من الصعب وسريعة "دائما nvarchar" القاعدة لأنه يمكن أن يكون مضيعة كاملة في كثير من الحالات - وخاصة ETL من ASCII/EBCDIC أو معرفات رمز الأعمدة التي غالبا ما تكون مفاتيح مفاتيح خارجية.

من ناحية أخرى, هناك الكثير من الحالات من الأعمدة ، حيث أود أن تأكد من أن تسأل هذا السؤال في وقت مبكر إذا لم أحصل على الجاد والسريع تجب على الفور ، وأود أن جعل العمود nvarchar.

للحصول على التطبيق الخاص بك ، nvarchar على ما يرام لأن حجم قاعدة البيانات هو صغير.قائلا "دائما استخدام nvarchar" هو تبسيط مفرط.إذا كنت غير مطلوب لتخزين الأشياء مثل كانجي أو غيرها من أحرف مجنونة استخدام VARCHAR سوف تستخدم مساحة أقل كثيرا.سلفي في وظيفتي الحالية مصممة شيء باستخدام NVARCHAR عندما لم يكن هناك حاجة.نحن في الآونة الأخيرة تحولت إلى VARCHAR و حفظ 15 GB على هذا الجدول (لقد كان في غاية كتابة).وعلاوة على ذلك, إذا كان لديك ثم فهرس على تلك الطاولة كنت ترغب في تضمين هذا العمود أو جعل مؤشر مركب ، لقد جعلت مؤشر حجم الملف أكبر.

يكون مجرد التفكير في المقرر ؛ في SQL والتنمية بيانات التعاريف يبدو نادرا ما تكون "الإجابة الافتراضية" (بخلاف تجنب المؤشرات في جميع التكاليف ، بالطبع).

لا تتردد في إضافة بعد آخر الجواب هنا وهناك بالفعل عدد غير قليل ، ولكن بعض النقاط التي لم مصنوع أو غير واضح.

الأولى: هل لا دائما استخدام NVARCHAR.هذا خطير جدا ، وغالبا ما تكون مكلفة ، موقف / النهج.وليس من الأفضل أن نقول "أبدا استخدام رؤوس مؤشرات" لأنها في بعض الأحيان أكثر الوسائل فعالية في حل مشكلة معينة ، و العمل المشترك حول القيام WHILE حلقة ستكون دائما تقريبا أبطأ من صحيح يتم المؤشر.

المرة الوحيدة التي يجب عليك استخدام مصطلح "دائما" عند إسداء المشورة إلى "دائما يفعل ما هو أفضل لهذا الوضع".منح هذا هو في كثير من الأحيان من الصعب تحديد ، وخصوصا عندما تحاول أن توازن بين تحقيق مكاسب قصيرة الأجل في التنمية وقت (المدير:"نحن بحاجة إلى هذه الميزة -- التي لم تعرف حتى الآن فقط -- قبل أسبوع!") مع تكاليف الصيانة على المدى الطويل (مدير في البداية ضغط فريق لإكمال 3 أشهر المشروع في 3 أسابيع سباق:"لماذا نحن بعد الأداء هذه المشاكل ؟ كيف يمكننا ان تفعل X والتي لا يوجد لديه المرونة ؟ لا يمكننا تحمل العدو أو اثنين لإصلاح هذه.ماذا يمكننا الحصول على القيام به في الأسبوع حتى نتمكن من العودة إلى أولوية البنود ؟ ونحن بالتأكيد بحاجة لقضاء المزيد من الوقت في التصميم لذلك هذا لا يحدث دائما!").

الثانية: @gbn الجواب اللمسات على بعض النقاط الهامة التي يجب مراعاتها عند اتخاذ بعض البيانات نمذجة القرارات عند المسار ليست واضحة 100%.ولكن هناك أكثر من ذلك للنظر في:

  • حجم ملفات تسجيل المعاملات
  • الوقت المستغرق في تكرار (في حالة استخدام النسخ المتماثل)
  • الوقت الذي يستغرقه ETL (إذا ETLing)
  • الوقت المستغرق لشحن سجلات عن بعد ونظام استعادة (إذا باستخدام سجل الشحن)
  • حجم النسخ الاحتياطي
  • طول الوقت الذي يستغرقه لإكمال النسخ الاحتياطي
  • طول الوقت الذي يستغرقه للقيام استعادة (هذا قد يكون مهما في بعض اليوم؛ -)
  • حجم الحاجة tempdb
  • أداء المشغلات (على إدراج و حذف الجداول التي يتم تخزينها في tempdb)
  • أداء الصف الإصدار (إذا باستخدام عزل لقطة منذ مخزن الإصدار في tempdb)
  • القدرة على الحصول على الجديد مساحة القرص عند المدير المالي يقول أنها أنفقت فقط 1 مليون دولار على سان العام الماضي و حتى لا يأذن آخر $250k للحصول على سعة تخزين إضافية
  • طول الوقت الذي يستغرقه للقيام إدراج عمليات التحديث
  • طول الوقت الذي يستغرقه للقيام مؤشر الصيانة
  • إلخ, إلخ, إلخ.

إضاعة الفضاء لديها ضخمة التعاقبي على النظام بأكمله.كتبت مقالا الخوض في التفاصيل واضحة في هذا الموضوع: القرص رخيص!اورلي ؟ (التسجيل مجاني المطلوبة ؛ آسف أنا لا تحكم السياسة).

الثالث: في حين أن بعض الإجابات بشكل غير صحيح مع التركيز على "هذا هو التطبيق صغير" الجانب ، وبعضها بشكل صحيح مما يشير إلى "استخدام ما هو مناسب" ، أي من الإجابات قدمت التوجيه الحقيقي O. P.تفصيل مهم ذكر في السؤال هو أن هذه هي صفحة ويب المدرسة.كبيرة!لذا نحن يمكن أن تشير إلى أن:

  • حقول الطالب و/أو أعضاء هيئة التدريس الأسماء ربما يكون NVARCHAR منذ مرور الوقت ، هو فقط الحصول على المزيد من المرجح أن أسماء من ثقافات أخرى سوف تظهر في تلك الأماكن.
  • ولكن عنوان الشارع والمدينة الأسماء ؟ الغرض من التطبيق هو لم يذكر (كان يمكن أن يكون مفيدا) ولكن على افتراض عنوان السجلات ، إن وجدت ، تتعلق فقط في منطقة جغرافية معينة (أي ، اللغة / الثقافة) ، ثم استخدام VARCHAR مع الرمز المناسب الصفحة (والتي يتم تحديدها من جمع الميدان).
  • إن تخزين الدولة و/أو بلد ISO رموز (لا حاجة لتخزين INT / TINYINT منذ ISO رموز ثابتة طول الإنسان للقراءة و معيار :) استخدام CHAR(2) على اثنين من رموز الرسالة ، CHAR(3) إذا كنت تستخدم 3 رموز الرسالة.و النظر في استخدام ثنائي جمع مثل Latin1_General_100_BIN2.
  • إن تخزين الرموز البريدية (أيرموز البريدي), استخدام VARCHAR لأنه هو معيار دولي أبدا استخدام أي حرف خارج A-Z.و نعم لا تزال تستخدم VARCHAR حتى لو كان فقط تخزين لنا رموز البريدي وليس الباحث منذ رموز البريدي ليست أرقام ، فهي سلاسل و بعض منهم لديهم الرائدة "0".و النظر في استخدام ثنائي جمع مثل Latin1_General_100_BIN2.
  • إن تخزين عناوين البريد الإلكتروني و/أو عناوين url استخدام NVARCHAR لأن كلا من هؤلاء الآن يمكن أن تحتوي على أحرف Unicode.
  • وهلم جرا....

الرابع: الآن أن لديك NVARCHAR البيانات تناول ضعفي مساحة من أنه يحتاج إلى البيانات التي تناسبها بشكل جيد في VARCHAR ("يناسب بشكل جيد" = لا يتحول إلى "?") و بطريقة ما كما لو كان بفعل السحر, التطبيق لم تنمو الآن هناك الملايين من السجلات في واحد على الأقل من هذه المجالات حيث معظم الصفوف ASCII القياسية ولكن بعض تحتوي على أحرف Unicode لذلك عليك أن تبقي NVARCHAR, يجب مراعاة ما يلي:

  1. إذا كنت تستخدم SQL Server 2008 - 2016 RTM و على طبعة المؤسسة ، أو إذا كنت تستخدم SQL Server 2016 SP1 (الذي جعل ضغط البيانات المتاحة في جميع الإصدارات) أو أحدث ، ثم يمكنك تمكين ضغط البيانات.ضغط البيانات يمكن (ولكن لن "دائما") ضغط بيانات Unicode في NCHAR و NVARCHAR المجالات.تحديد العوامل هي:

    1. NCHAR(1 - 4000) و NVARCHAR(1 - 4000) استخدام معيار ضغط نظام يونيكود, ولكن فقط البدء في SQL Server 2008 R2 فقط في صف البيانات لا تجاوز!هذا يبدو أن يكون أفضل من العادية الصف / صفحة خوارزمية ضغط.
    2. NVARCHAR(MAX) و XML (و أعتقد أيضا VARBINARY(MAX), TEXT, ، NTEXT) البيانات في الصف (وليس خارج الصف في لوب أو تجاوز صفحات) على الأقل يمكن أن تكون صفحة مضغوط ، ولكن لا الصف مضغوط.بالطبع, صفحة ضغط يعتمد على حجم في الصف القيمة:أنا اختبرت مع VARCHAR(MAX) ورأى أن 6000 حرف/بايت الصفوف لا ضغط ، ولكن 4000 حرف/بايت الصفوف فعلت.
    3. أي خارج الصف البيانات ، لوب أو OVERLOW = لا ضغط بالنسبة لك!
  2. إذا كنت تستخدم SQL Server 2005 أو 2008 - 2016 RTM ، لا على Enterprise Edition, هل يمكن أن يكون اثنين من المجالات:واحد VARCHAR واحد NVARCHAR.على سبيل المثال, دعونا نقول كنت تخزين عناوين المواقع التي هي في معظمها كل قاعدة أحرف ASCII (القيم 0 - 127) وبالتالي تنسجم VARCHAR, ولكن في بعض الأحيان قد أحرف Unicode.المخطط يمكن أن تشمل ما يلي 3 مجالات:

      ...
      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))
    );
    

    في هذا النموذج لك فقط اختر من [URL] عمود محسوب.لإدخال وتحديث, يمكنك تحديد أي مجال استخدام من رؤية ما إذا كان تحويل يغير واردة القيمة ، والتي يجب أن تكون من NVARCHAR نوع:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
    
  3. يمكنك GZIP القيم الواردة في VARBINARY(MAX) ثم قم بفك ضغط على طريقة للخروج:

    • ل SQL Server 2005 - 2014:يمكنك استخدام SQLCLR. SQL# (أ SQLCLR المكتبة التي كتبت) يأتي مع Util_GZip و Util_GUnzip في نسخة مجانية
    • ل SQL Server 2016 الجديدة:يمكنك استخدام المدمج في COMPRESS و DECOMPRESS الوظائف التي هي أيضا GZip.
  4. إذا كنت تستخدم SQL Server عام 2017 أو الأحدث, يمكنك أن تبحث في اتخاذ الجدول متفاوت المسافات الفهرس كولومنستوري.

  5. في حين أن هذا ليس خيارا قابلا للتطبيق بعد SQL Server 2019 يدخل الوطنية لدعم UTF-8 في VARCHAR / CHAR أنواع البيانات.هناك حاليا الكثير من البق مع ذلك من أجل أن تستخدم إلا إذا كانت ثابتة ، ثم هذا هو خيار بعض السيناريوهات.يرجى الاطلاع على بلدي بوست" ، الأم UTF-8 الدعم في SQL Server 2019:المنقذ أو كاذبة النبي ؟ "،على تحليل مفصل من هذه الميزة الجديدة.

منذ التطبيق الخاص بك هو صغير ، هناك أساسا أي ملموس زيادة تكلفة استخدام nvarchar على varchar و يمكنك حفظ نفسك الصداع المحتملة على الطريق إذا كنت بحاجة لتخزين بيانات unicode.

عموما الحديث ؛ تبدأ مع أغلى نوع البيانات الذي يحتوي على أقل من القيود. وضعه في الإنتاج.إذا كان الأداء يبدأ مسألة معرفة ما هو في الواقع يجري تخزينها في تلك nvarchar الأعمدة.هل هناك أية أحرف في هناك التي لا تنسجم مع varchar?إن لم يكن التبديل إلى varchar.لا تحاول ما قبل الأمثل قبل أن تعرف أين الألم.تخميني هو أن الاختيار بين nvarchar/varchar ليس ما سوف تبطئ التطبيق الخاص بك في foreseable المستقبل.سيكون هناك أجزاء أخرى من التطبيق حيث ضبط الأداء سوف تعطيك أكثر من ذلك بكثير الدوي دولار.

بالنسبة السنوات القليلة الماضية أن جميع مشاريعنا استخدمت NVARCHAR على كل شيء, حيث أن جميع هذه المشاريع متعددة اللغات.استيراد بيانات من مصادر خارجية (مثلملف ASCII ، إلخ.) يصل تحويلها إلى Unicode قبل أن يتم إدراجها في قاعدة البيانات.

أنا لم تواجه أي مشاكل تتعلق بالأداء من أكبر إلخ.الفهارس استخدام المزيد من الذاكرة ، ولكن الذاكرة رخيصة.

ما إذا كان يمكنك استخدام الإجراءات المخزنة أو بناء SQL على الطاير التأكد من أن جميع ثوابت السلسلة مسبوقة بـ N (مثلا ، مجموعة @فو = N'Hello العالم.';) لذا المستمر هو أيضا Unicode.هذا يتجنب أي نوع السلسلة التحويل في وقت التشغيل.

YMMV.

أستطيع أن أتكلم من تجربة في هذا ، حذار من nvarchar.إلا إذا كنت على الاطلاق تتطلب هذه البيانات نوع الحقل يدمر الأداء على أكبر قاعدة البيانات الخاصة بنا.لقد ورثت قاعدة البيانات التي كانت تتألم من حيث الأداء و الفضاء.كنا قادرين على تقليل 30GB قواعد البيانات في الحجم بنسبة 70%!كانت هناك بعض التعديلات التي تم إجراؤها للمساعدة في الأداء ولكن أنا متأكد من أن varchar's ساعد بشكل كبير مع ذلك أيضا.إذا كانت قاعدة البيانات الخاصة بك لديه القدرة على النمو الجداول مليون + سجلات البقاء بعيدا عن nvarchar في جميع التكاليف.

أنا أتعامل مع هذا السؤال في العمل في كثير من الأحيان:

  • FTP يتغذى من المخزون التسعير - وصف البند وغيرها من النص في nvarchar عندما varchar عملت غرامة.تحويل هذه varchar تخفيض حجم الملف تقريبا في نصف ساعدت حقا مع الإضافات.

  • السيناريو أعلاه عملت بشكل جيد حتى شخص وضع طابع خاص في وصف البند (ربما العلامات التجارية لا تذكر)

أنا لا تزال لا تستخدم nvarchar في كل مرة على varchar.إذا كان هناك أي شك أو احتمال الأحرف الخاصة, يمكنني استخدام nvarchar.أجد استخدام varchar في الغالب عندما أكون في السيطرة 100 ٪ من ما هو ملء الحقل.

السبب في كل هذا النقاش لم يكن هناك أي ذكر UTF-8?كونها قادرة على تخزين الكامل يونيكود تمتد من الشخصيات لا يعني دائما تخصيص اثنين بايت لكل حرف (أو "نقطة رمز" استخدام UNICODE الأجل).كل ASCII هو UTF-8.لا SQL Server تحقق VARCHAR() حقول النص صارمة ASCII (أيأعلى بايت بت صفر)?اتمنى ذلك

ثم إذا كنت ترغب في تخزين unicode و تريد التوافق مع كبار السن ASCII-فقط التطبيقات ، وأعتقد باستخدام VARCHAR() و UTF-8 سيكون الرصاصة السحرية:يستخدم فقط مساحة أكبر عندما يحتاج إلى.

بالنسبة لأولئك غير مألوفة مع UTF-8 ، قد أوصي التمهيدي.

سوف يكون هناك حالات استثنائية عندما أنت تريد أن تقيد عمدا نوع البيانات لضمان لا تحتوي على شخصيات من مجموعة معينة.على سبيل المثال, كان السيناريو حيث كنت بحاجة لتخزين اسم المجال في قاعدة البيانات الخاصة بنا.تدويل أسماء النطاقات لم يكن عليها في ذلك الوقت لذلك كان من الأفضل للحد من المدخلات على مستوى القاعدة, و تساعد على تجنب أي مشاكل محتملة.

إذا كنت تستخدم NVARCHAR فقط لأن نظام تخزين الإجراء يتطلب ذلك حدوث الأكثر شيوعا كونها غير مفهوم sp_executesql, و ديناميكية SQL طويلة جدا ، يمكنك أن تكون أفضل حالا من منظور الأداء تفعل كل التلاعب سلسلة (سلسلة الاستبدال.... الخ) في VARCHAR ثم تحويل النتيجة النهائية NVARCHAR والتغذية في proc المعلمة.لذلك لا ، لا تستخدم دائما NVARCHAR!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top