जब SQL सर्वर 2019 के साथ `nvarchar / nchar` का उपयोग किया जा रहा है?


11

SQL सर्वर 2019 के साथ Microsoft UTF-8 समर्थनCHAR और VARCHARडेटा प्रकारों के लिए परिचय देता है और कहता है:

यह सुविधा उपयोग में निर्धारित चरित्र के आधार पर महत्वपूर्ण भंडारण बचत प्रदान कर सकती है। उदाहरण के लिए, एक मौजूदा कॉलम डेटा प्रकार को एनसीएचएआर (10) से सीएचएआर (10) से बदलकर एक यूटीएफ -8 सक्षम टकराव का उपयोग करके स्टोरेज आवश्यकताओं में लगभग 50% की कमी में बदल जाता है। यह कमी इसलिए है क्योंकि NCHAR (10) को भंडारण के लिए 22 बाइट्स की आवश्यकता होती है, जबकि CHAR (10) को एक ही यूनिकोड स्ट्रिंग के लिए 12 बाइट्स की आवश्यकता होती है।

UTF-8 हर स्क्रिप्ट का समर्थन करता है, इसलिए मूल रूप से हम यूनिकोड डेटा को varcharऔर charकॉलमों में संग्रहीत करना शुरू कर सकते हैं। और जैसा कि प्रलेखन में कहा गया है, यह तालिकाओं और अनुक्रमित के आकार को कम कर सकता है, और वहां से हम और भी बेहतर प्रदर्शन प्राप्त कर सकते हैं, क्योंकि डेटा की छोटी मात्रा को पढ़ा जाता है।

मुझे आश्चर्य है कि इसका मतलब यह है कि हम यूटीएफ -16 को लागू करने वाले कॉलम nvarcharऔर ncharकॉलम का उपयोग करना बंद कर सकते हैं ?

क्या कोई भी परिदृश्य और कारण को इंगित कर सकता है, न कि UTFएन्कोडिंग के साथ चार डेटा प्रकारों का उपयोग करने के लिए और एन-चार लोगों का उपयोग जारी रखने के लिए?


आप इसका परीक्षण क्यों नहीं करते और वापस रिपोर्ट करते हैं? हमें यह भी बताएं कि आप नेवरचार्ज से विचर में बदलने के लिए कितना प्रयास किया है - परिवर्तन तालिकाओं में कितना समय लगा, और आपने परीक्षण में कितना समय बिताया, और आपके सामने क्या मुद्दे आए।
कॉलिन टी हार्ट

@ Colin'tHart यदि कोई ज्ञात समस्या या विचार नहीं हैं, तो मैं डेटा को स्थानांतरित करने की योजना बना रहा हूं क्योंकि मेरा मानना ​​है कि कम डेटा पढ़ने से सिस्टम के लिए बेहतर प्रदर्शन होगा। रूपांतरण के बारे में - यह निश्चित रूप से समय लेगा, खासकर यदि आपके पास दिए गए कॉलम के साथ अनुक्रमित हैं - उन्हें पुनर्निर्माण करने की आवश्यकता है, लेकिन मुझे विश्वास है कि यह अच्छी तरह से भुगतान करेगा। बेशक, मैं जल्द ही प्रदर्शन प्रभाव का परीक्षण करने जा रहा हूं, बस किसी भी मुद्दे की तलाश में हूं जो प्रवासन को अनावश्यक बना देगा।
11

ध्यान दें कि SQL सर्वर पृष्ठ या ROW संपीड़न का उपयोग करते समय NVarchar स्तंभों के लिए यूनिकोड संपीड़न का समर्थन करता है। docs.microsoft.com/en-us/sql/relational-dat डेटाबेस/…
डेविड ब्राउन - Microsoft

1
यह ध्यान देने योग्य है कि जब आप "ASCII- जैसा डेटा" संग्रहीत कर रहे हैं तो UTF-8 अंतरिक्ष को बचा सकता है, यह अपने आप में संपीड़न नहीं है, और इस तरह से गलत नहीं होना चाहिए। उदाहरण के लिए, यदि आप किसी डेटाबेस में मुख्य रूप से चीनी नाम संग्रहीत कर रहे हैं, तो आप CHARयूनिकोड प्रकारों की तुलना में यूटीएफ -8 प्रकारों का उपयोग करने से बदतर होंगे (संपीड़न के साथ या बिना, क्योंकि अंततः डेटा को संसाधित करने के लिए असम्पीडित होने की आवश्यकता होती है)। यह भी विचार करें कि विंडोज का मूल स्ट्रिंग प्रकार यूनिकोड है, इसलिए UTF-8 तार को अक्सर डिकोड करने की आवश्यकता होती है। इसमें शामिल ट्रेडऑफ का मतलब है कि यह संभव नहीं है कि Nप्रकार जल्द ही किसी भी समय सेवानिवृत्त हो जाएंगे।
जेरोइन मोस्टर्ट

1
UTF-8 के लिए # 1 "किलर ऐप" CHARशायद लिनक्स पर SQL सर्वर है, अगर इंजन को सीधे UTF-8 के रूप में स्ट्रिंग के प्रसंस्करण के लिए मूल समर्थन मिलता है - यहाँ UTF-8 "मूल" वर्ण सेट (अधिक या कम) है और तार को UTF-16 के आसपास रखना कम कुशल विकल्प है। यह विंडोज पर उन जगहों पर उपयोग करने के लिए भी चोट नहीं पहुंचाएगा जहां आप पहले से ही उपयोग कर रहे हैं CHAR, निश्चित रूप से, कोलाज को संग्रहीत किए जाने वाले वर्णों को प्रतिबंधित करने के बाद कभी भी आकर्षक नहीं बनाया गया है।
जीरोन मोस्टर्ट

जवाबों:


6

यह तालिकाओं और अनुक्रमित के आकार को कम कर सकता है (जोर दिया)

आकार में कमी केवल तभी संभव है सबसे पात्रों में से अनिवार्य रूप से कर रहे हैं [space], 0 - 9, A - Z, a - z, और कुछ बुनियादी विराम चिह्न। वर्णों के उस विशिष्ट सेट के बाहर (व्यावहारिक उपयोग की शर्तों में, मानक ASCII मान 32 - 126), आप आकार में सबसे अच्छा बराबर NVARCHAR/ UTF-16, या कई मामलों में बड़े होंगे।

मैं डेटा को माइग्रेट करने की योजना बना रहा हूं क्योंकि मेरा मानना ​​है कि कम डेटा पढ़ने से सिस्टम के लिए बेहतर प्रदर्शन होगा।

सावधान रहे। UTF-8 एक जादू नहीं है "सब कुछ ठीक करें" स्विच। अन्य सभी चीजें समान हैं, हां, कम पढ़ने से प्रदर्शन में सुधार होता है। लेकिन यहां "अन्य सभी चीजें" समान नहीं हैं । यहां तक ​​कि केवल मानक ASCII वर्णों को संग्रहीत करते समय (जिसका अर्थ है: सभी वर्ण 1 बाइट हैं, इसलिए स्टोर करने की तुलना में आधे स्थान की आवश्यकता होती है NVARCHAR), UTF-8 का उपयोग करने के लिए मामूली प्रदर्शन जुर्माना है। मेरा मानना ​​है कि यह समस्या यूटीएफ -8 के परिवर्तनशील लंबाई वाले एन्कोडिंग के कारण है, जिसका अर्थ है कि प्रत्येक बाइट की व्याख्या की जानी चाहिए क्योंकि यह जानने के लिए पढ़ा जाता है कि क्या यह एक पूर्ण चरित्र है या यदि अगला बाइट इसका एक हिस्सा है। इसका मतलब है कि सभी स्ट्रिंग ऑपरेशनों को शुरुआत में शुरू करने और बाइट-बाय-बाइट की आवश्यकता है। दूसरी ओर,NVARCHAR / UTF-16 हमेशा 2 बाइट्स होता है (यहां तक ​​कि अनुपूरक वर्ण भी दो 2-बाइट कोड पॉइंट्स से युक्त होते हैं), इसलिए 2-बाइट विखंडू में सब कुछ पढ़ा जा सकता है।

मेरे परीक्षण में, यहां तक ​​कि केवल मानक ASCII वर्णों के साथ, डेटा को UTF-8 के रूप में संग्रहीत करने से बीता समय की कोई बचत नहीं हुई, लेकिन निश्चित रूप से CPU समय के लिए बदतर था। और वह डेटा कम्प्रेशन के बिना था, इसलिए कम से कम डिस्क स्थान का उपयोग किया गया था। लेकिन, संपीड़न का उपयोग करते समय, UTF-8 के लिए आवश्यक स्थान केवल 1% था - 1.5% छोटा। तो प्रभावी रूप से कोई अंतरिक्ष बचत UTF-8 के लिए अभी तक उच्च CPU समय नहीं है।

NVARCHAR(MAX)यूनिकोड संपीड़न के बाद से चीजें अधिक जटिल हो जाती हैं क्योंकि यह डेटाटाइप के साथ काम नहीं करता है, भले ही मूल्य पंक्ति में संग्रहीत होने के लिए पर्याप्त छोटा हो। लेकिन, यदि डेटा काफी छोटा है, तो इसे अभी भी रो या पेज संपीड़न (जिस स्थिति में यह वास्तव में UTF-8 से तेज हो जाता है) से लाभ होना चाहिए। हालाँकि, ऑफ-रो डेटा किसी भी संपीड़न का उपयोग नहीं कर सकता है। फिर भी, तालिका को एक क्लस्टर्ड कॉलमस्टोरस्टोर इंडेक्स बनाने से इसका आकार बहुत कम हो जाता है NVARCHAR(MAX)(भले ही यह अभी भी UTF-8 से थोड़ा बड़ा हो, जब क्लस्टर किए गए कॉलम के आधार पर इंडेक्स का उपयोग किया जाता है)।

क्या कोई व्यक्ति परिदृश्य और कारण को इंगित कर सकता है, यूटीएफ एन्कोडिंग के साथ चार डेटा प्रकारों का उपयोग करने के लिए नहीं

निश्चित रूप से। वास्तव में, मैं वास्तव में इसे ज्यादातर मामलों में उपयोग करने के लिए एक सम्मोहक कारण नहीं ढूंढता। एकमात्र परिदृश्य जो वास्तव में UTF-8 से लाभान्वित होता है:

  1. डेटा ज्यादातर मानक ASCII है (मान 0 - 127)
  2. इसे यूनिकोड होने की आवश्यकता है क्योंकि इसे किसी एकल 8-बिट कोड पृष्ठ (यानी ) पर उपलब्ध वर्णों की एक विस्तृत श्रृंखला को संग्रहीत करने की आवश्यकता हो सकती हैVARCHAR
  3. अधिकांश डेटा ऑफ-रो स्टोर किया जाता है (इसलिए पृष्ठ संपीड़न भी काम नहीं करता है)
  4. आपके पास पर्याप्त डेटा है जिसकी आपको आवश्यकता है / गैर-क्वेरी-प्रदर्शन कारणों के लिए आकार कम करना चाहता है (जैसे बैकअप आकार कम करना, बैकअप के लिए आवश्यक समय कम करना / पुनर्स्थापित करना, आदि)
  5. आप Clustered Columnstore Index का उपयोग नहीं कर सकते हैं (शायद तालिका का उपयोग इस मामले में प्रदर्शन को बदतर बनाता है?)

मेरे परीक्षण से पता चलता है कि लगभग सभी मामलों में, NVARCHAR तेज था, खासकर जब अधिक डेटा था। वास्तव में, 21k पंक्तियों के साथ औसतन 5k वर्ण प्रति पंक्ति में यूटीएफ -8 के लिए 165 एमबी और NVARCHARअसम्पीडित के लिए 236 एमबी की आवश्यकता होती है । और फिर भी NVARCHARबीते समय में 2x अधिक तेज था, और सीपीयू समय में कम से कम 2x तेज (कभी-कभी अधिक)। फिर भी, इसने डिस्क पर 71 एमबी अधिक लिया।

उस के बाहर, मैं अभी भी UTF-8 का उपयोग करने की सिफारिश नहीं करूंगा, कम से कम CTP 2 के रूप में, विभिन्न प्रकार के बग के कारण जो मुझे इस सुविधा में मिला है।

इस नई सुविधा के विस्तृत विश्लेषण के लिए, जिसमें UTF-16 और UTF-8 के बीच अंतर और उन बगों की एक सूची शामिल है, कृपया मेरी पोस्ट देखें:

SQL Server 2019 में मूल निवासी UTF-8 समर्थन: उद्धारकर्ता या गलत पैगंबर?


12

UTF-8 समर्थन आपको विकल्पों का एक नया सेट देता है। संभावित अंतरिक्ष बचत ( पंक्ति या पृष्ठ संपीड़न के बिना ) एक विचार है, लेकिन प्रकार और एन्कोडिंग का विकल्प संभवतः तुलना, छंटाई, डेटा आयात और निर्यात के लिए वास्तविक आवश्यकताओं के आधार पर बनाया जाना चाहिए ।

आपको अपने विचार से अधिक बदलाव करने की आवश्यकता हो सकती है, जैसे कि एक nchar(1)प्रकार दो बाइट्स प्रदान करता है। यह BMP (कोड पॉइंट 000000 से 00FFFF) में किसी भी वर्ण को संग्रहीत करने के लिए पर्याप्त है । उस श्रेणी के कुछ अक्षर UTF-8 में सिर्फ 1 बाइट के साथ एन्कोडेड होंगे जबकि अन्य को 2 या 3 बाइट्स की आवश्यकता होगी ( अधिक विवरण के लिए यह तुलना चार्ट देखें)। इसलिए, UTF-8 में वर्णों के एक ही सेट की कवरेज सुनिश्चित करने की आवश्यकता होगी char(3)

उदाहरण के लिए:

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 char(1) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

परिचित त्रुटि देता है:

Msg 8152, Level 16, State 30, Line xxx
String या बाइनरी डेटा को छोटा किया जाएगा।

या यदि ट्रेस ध्वज 460 सक्रिय है:

Msg 2628, Level 16, State 1, Line xxx
String या बाइनरी डेटा को तालिका '@T', कॉलम 'UTF8' में काट दिया जाएगा। काट दिया गया मान: ''।

UTF8 कॉलम का विस्तार करना char(2)या varchar(2)उसके लिए त्रुटि का समाधान करना NCHAR(911):

DECLARE @T AS table 
(
    n integer PRIMARY KEY,
    UTF16 nchar(1) COLLATE Latin1_General_CI_AS,
    UTF8 varchar(2) COLLATE Latin1_General_100_CI_AS_SC_UTF8
);

INSERT @T (n, UTF16, UTF8)
SELECT 911, NCHAR(911), NCHAR(911);

हालाँकि, यदि यह उदाहरण के लिए NCHAR(8364), आपको कॉलम को आगे, char(3)या तक विस्तारित करना होगा varchar(3)

यह भी ध्यान दें कि UTF-8 समतुल्य सभी पूरक वर्णों का उपयोग करते हैं, इसलिए प्रतिकृति के साथ काम नहीं करेंगे

कुछ और के अलावा, UTF-8 समर्थन केवल इस समय पूर्वावलोकन में है, इसलिए उत्पादन उपयोग के लिए उपलब्ध नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.