क्या सभी पाठ-आधारित फ़ील्ड के लिए जेनेरिक varchar (255) का उपयोग करने के नुकसान हैं?


100

मैं एक है contactsतालिका जो इस तरह के रूप में फ़ील्ड शामिल हैं postcode, first name, last name, town, country, phone numberआदि, जो सभी के रूप में परिभाषित कर रहे हैं VARCHAR(255), भले ही इन क्षेत्रों में से कोई भी कभी 255 वर्ण होने के करीब आ जाएगा। (यदि आप सोच रहे हैं, यह इस तरह है क्योंकि रूबी ऑन रेल माइग्रेशन मैपिंग स्ट्रिंग फ़ील्ड्स को VARCHAR(255)डिफ़ॉल्ट रूप से करता है और मैंने इसे ओवरराइड करने के लिए कभी परेशान नहीं किया है)।

चूंकि VARCHAR केवल (क्षेत्र लंबाई के साथ) क्षेत्र की वास्तविक वर्णों की संख्या का संग्रह किया जायेगा, वहाँ किसी भी विशिष्ट लाभ (प्रदर्शन या अन्यथा) का उपयोग करते हुए, कहते हैं, करने के लिए है VARCHAR(16)से अधिक VARCHAR(255)?

इसके अतिरिक्त, इन क्षेत्रों में से अधिकांश उन पर अनुक्रमित हैं। क्या मैदान पर बड़ा VARCHAR आकार सूचकांक के आकार या प्रदर्शन को बिल्कुल प्रभावित करता है?

FYI करें मैं MySQL 5 का उपयोग कर रहा हूं।


2
@ceejayoz, यह कहते हुए कि स्वीकृत उत्तर गलत है, यह बताए बिना कि वास्तव में मदद क्यों नहीं की जाती है। इससे भी बुरा यह है कि स्वीकृत उत्तर समय के साथ बदल सकता है और आपकी टिप्पणी लोगों को भ्रमित करेगी कि नए स्वीकृत उत्तर को गलत माना जाए।
गिली

1
@ गिल्ली ने ओपी के रूप में अपनी टिप्पणी को स्पष्ट रूप से स्वीकार कर लिया। अच्छे अंक, भविष्य में मैं इंगित करूंगा कि मैं किस उत्तर के बारे में बात कर रहा हूं और क्यों।
सिजयोज

इस डुप्लिकेट प्रश्न पर कुछ अन्य जवाब, stackoverflow.com/questions/1262174/…
जेम्स मैकमोहन

जवाबों:


129

भंडारण में, VARCHAR(255)किसी दिए गए पंक्ति पर केवल उस लंबाई को संग्रहीत करने के लिए पर्याप्त स्मार्ट है, CHAR(255)जिसके विपरीत हमेशा 255 वर्ण संग्रहीत होंगे।

लेकिन जब से आपने MySQL के साथ इस प्रश्न को टैग किया है, मैं एक MySQL-विशिष्ट टिप का उल्लेख करूंगा: चूंकि पंक्तियों को स्टोरेज इंजन लेयर से SQL लेयर में कॉपी किया जाता है, फिक्स्ड-चौड़ाई वाली पंक्तियों के साथ काम करने का लाभ प्राप्त VARCHARकरने के CHARलिए फ़ील्ड्स को कनवर्ट किया जाता है। तो स्मृति में तार आपके घोषित कॉलम की अधिकतम लंबाई तक गद्देदार हो जाते हैं VARCHAR

जब आपकी क्वेरी स्पष्ट रूप से एक अस्थायी तालिका उत्पन्न करती है, उदाहरण के लिए छँटाई करते समय या GROUP BY, यह बहुत सारी मेमोरी का उपयोग कर सकती है। यदि आप VARCHAR(255)डेटा के लिए बहुत सारे फ़ील्ड का उपयोग करते हैं , जो लंबे समय तक होने की आवश्यकता नहीं है, तो यह अस्थायी तालिका को बहुत बड़ा बना सकता है।

आप यह भी जानना पसंद कर सकते हैं कि इस "पेडिंग आउट" व्यवहार का अर्थ है कि एक स्ट्रिंग जिसे utf8 वर्ण सेट पैड के साथ तीन बाइट्स प्रति वर्ण के लिए घोषित किया गया है, यहां तक ​​कि स्ट्रिंग्स के लिए आप एकल-बाइट सामग्री (जैसे एससीआईआई या लैटिन 1 वर्ण) के साथ स्टोर करते हैं। और इसी तरह utf8mb4 कैरेक्टर सेट से स्ट्रिंग को मेमोरी में चार बाइट्स प्रति कैरेक्टर पैड हो जाता है।

इसलिए VARCHAR(255)utf8 में "नो ओपिनियन" जैसी शॉर्ट स्ट्रिंग को डिस्क पर 11 बाइट्स लेते हैं (दस लोअर-चारसेट कैरेक्टर, प्लस एक बाइट लंबाई के लिए), लेकिन इसमें 765 बाइट्स मेमोरी में लगते हैं, और इस तरह टेम्पर टेबल या सॉर्ट किए गए परिणाम।

मैंने MySQL उपयोगकर्ताओं की मदद की है, जिन्होंने अनजाने में 1.5GB टेम्‍प टेबलों को बार-बार बनाया और उनकी डिस्क स्‍पेस को भर दिया। उनके पास बहुत सारे VARCHAR(255)स्तंभ थे जो व्यवहार में बहुत कम तारों को संग्रहीत करते थे।

आपके द्वारा संग्रहीत किए जाने वाले डेटा के प्रकार के आधार पर कॉलम को परिभाषित करना सबसे अच्छा है। यह आवेदन-संबंधी बाधाओं को लागू करने के लिए लाभ है, जैसा कि अन्य लोगों ने उल्लेख किया है। लेकिन इसके ऊपर बताए गए मैमोरी वेस्ट से बचने के शारीरिक फायदे हैं।

यह जानना मुश्किल है कि सबसे लंबा डाक पता क्या है, बेशक, यही वजह है कि बहुत से लोग एक लंबा चुनाव करते हैं VARCHARजो निश्चित रूप से किसी भी पते से अधिक लंबा है। और 255 प्रथागत है क्योंकि यह एक अधिकतम लंबाई है VARCHARजिसके लिए लंबाई को एक बाइट के साथ एन्कोड किया जा सकता है। यह VARCHARMySQL में अधिकतम लंबाई 5.0 से अधिक थी।


6
मुझे हमेशा लगता 255था कि स्ट्रिंग की लंबाई एक ही बाइट में फिट हो सकती है
BlueRaja - Danny Pflughoeft

3
@BlueRaja: यह संभवतः उन डेटाबेस के लिए सही था जिनकी आंतरिक फ़ाइल संरचना ने एक बाइट में एक स्ट्रिंग की लंबाई को एन्कोड किया था, या यदि उन्होंने एक ही बाइट में छोटे तारों को एन्कोड किया था। लेकिन यह अब अधिकांश डेटाबेस के लिए सही नहीं है।
बिल करविन

7
@BlueRaja: InnoDB निम्नलिखित वर्चर की लंबाई को संग्रहीत नहीं करता है, यह पंक्ति में सभी फ़ील्ड के लिए फ़ील्ड ऑफ़सेट की एक श्रृंखला संग्रहीत करता है। यदि कुल पंक्ति आकार 127 बाइट्स से कम है, या 2 बाइट्स हैं, तो ये फ़ील्ड ऑफ़सेट 1 बाइट हो सकते हैं। Forge.mysql.com/wiki/MySQL_Internals_InnoDB
बिल करविन

6
@BlueRaja: MyISAM (अभी भी इसका इस्तेमाल करने वालों के लिए) स्टोर की लंबाई करता है, और इन्हें 1 या 2 बाइट्स में स्टोर किया जा सकता है। हालाँकि: "जब index_read () या record_in_range के लिए हैंडलर को एक कुंजी भेजते हैं, तो हम चीजों को सरल बनाने के लिए VARCHAR के लिए हमेशा 2-बाइट की लंबाई का उपयोग करते हैं।" देखें forge.mysql.com/wiki/MySQL_Internals_MyISAM
विधेयक Karwin

1
एक प्रश्न - किसी भी क्षेत्र या स्वयं के आधार पर छँटाई और समूह?
रोहित बंगा

24

एक varchar (और संभवतः अधिक महत्वपूर्ण है, क्योंकि भंडारण और प्रसंस्करण हर सेकंड सस्ता मिलता है) के आकार और प्रदर्शन के विचारों के अलावा, varchar (255) का उपयोग करने का नुकसान "सिर्फ इसलिए" डेटा अखंडता कम हो गया है

स्ट्रिंग्स के लिए अधिकतम सीमा को परिभाषित करना आरडीबीएमएस में प्रवेश से आने वाले स्ट्रिंग्स की तुलना में लंबे समय तक रोकने के लिए और बफर ओवररन या अपवाद / त्रुटियों को उत्पन्न करने से रोकने के लिए एक अच्छी बात है जब डेटाबेस से मूल्यों को प्राप्त करना और पार्स करना जो कि अपेक्षा से अधिक बाइट्स हैं।

उदाहरण के लिए, यदि आपके पास एक ऐसा क्षेत्र है जो देश के संक्षिप्तीकरण के लिए दो-वर्ण स्ट्रिंग्स को स्वीकार करता है, तो आपके पास अपने उपयोगकर्ताओं (इस संदर्भ में, प्रोग्रामर) से पूरे देश के नाम इनपुट करने की अपेक्षा करने के लिए कोई बोधगम्य कारण नहीं है। चूंकि आप उन्हें "एंटीगुआ और बारबुडा" (एजी) या "हर्ड आइलैंड और मैकडोनाल्ड आइलैंड्स" (एचएम) में प्रवेश नहीं करना चाहते हैं, इसलिए आप इसे डेटाबेस लेयर पर अनुमति नहीं देते हैं। इसके अलावा, यह संभावना है कि कुछ प्रोग्रामर अभी तक डिजाइन प्रलेखन ( जो निश्चित रूप से मौजूद है ) आरटीएफएमड को ऐसा नहीं करने के लिए जानते हैं।

दो वर्णों को स्वीकार करने के लिए फ़ील्ड सेट करें और RDBMS को उसके साथ डील करने दें (या तो बिना किसी त्रुटि के अपने एसक्यूएल को खारिज करके ट्रंकटिंग या अनजाने में)।

वास्तविक डेटा के उदाहरण जिनके पास निश्चित लंबाई से अधिक होने का कोई कारण नहीं है:

  • कनाडाई पोस्टल कोड A1A1A1 प्रारूप के हैं और लंबाई में हमेशा 6 वर्ण होते हैं, यहां तक कि सांता क्लॉज़ के लिए (6 वर्ण उस स्थान को शामिल नहीं करता है जो कि सुगमता के लिए निर्दिष्ट किया जा सकता है)।
  • ईमेल पते - @ से पहले 64 बाइट्स तक, बाद में 255 बाइट्स तक। और कभी नहीं, ऐसा न हो कि आप इंटरनेट तोड़ दें।
  • उत्तर अमेरिकी फोन नंबर कभी भी 10 अंकों (देश कोड को छोड़कर) से अधिक नहीं होते हैं।
  • कंप्यूटर चलाने वाले (हाल के संस्करण) विंडोज में 63 बाइट्स से अधिक लंबे समय तक कंप्यूटर के नाम नहीं हो सकते हैं , हालांकि 15 से अधिक की सिफारिश नहीं की गई है और आपके विंडोज एनटीआर फार्म को तोड़ देगा।
  • राज्य संक्षिप्त रूप में 2 वर्ण हैं (ऊपर दिए गए देश कोड की तरह)
  • यूपीएस ट्रैकिंग नंबर या तो 18-, 12-, 11- या 9-वर्ण लंबे होते हैं। 18-कैरेक्टर नंबर "1Z" से शुरू होते हैं और 11-कैरेक्टर नंबर "T" से शुरू होते हैं, जो आपको आश्चर्यचकित करता है कि वे उन सभी पैकेजों को कैसे वितरित करते हैं यदि उन्हें अक्षरों और संख्याओं के बीच का अंतर नहीं पता है।

और इसी तरह...

अपने डेटा और उसकी सीमाओं के बारे में सोचने के लिए समय निकालें। यदि आप एक वास्तुकार, डेवलपर, या प्रोग्रामर हैं, तो यह आपका काम है

Varchar (255) के बजाय एक varchar (n) का उपयोग करके आप उस समस्या को समाप्त करते हैं जहाँ उपयोगकर्ता (अंतिम-उपयोगकर्ता, प्रोग्रामर, अन्य प्रोग्राम) अनपेक्षित रूप से लंबा डेटा दर्ज करते हैं जो बाद में आपके कोड को रोकने के लिए वापस आ जाएगा

और मैंने यह नहीं कहा कि आपको अपने आवेदन द्वारा उपयोग किए जाने वाले व्यवसाय तर्क कोड में इस प्रतिबंध को लागू नहीं करना चाहिए।


5
कनाडाई डाक कोड में वास्तव में 7 अंक हैं, बीच में स्थान महत्वपूर्ण है, और मेलिंग लेबल पर दिखाया जाना चाहिए। उत्तर अमेरिकी फोन नंबर एक से अधिक होने पर 10 अंकों से अधिक हो सकते हैं। यदि आप ठीक हैं कि फ़ोन नंबर एक्सटेंशन स्टोर नहीं कर पा रहे हैं, तो 10 अंक ठीक हैं, लेकिन आप शायद इसे पछतावा करेंगे।
काबी

3
डेटा अखंडता के लिए प्रतिबंधात्मक होने के लिए निश्चित रूप से एक मामला है। हालांकि, अभी भी बहुत प्रतिबंधक होना आसान है। आपके द्वारा नियंत्रित किए जाने वाले डेटा के लिए प्रतिबंधों को लागू करें, और उन डेटा आवश्यकताओं के लिए जिन पर आप नियंत्रण नहीं कर सकते, के लिए प्रतिबंध लागू करें । आपके फ़ोन नंबर और ई-मेल प्रतिबंध सेंस हैं (यह मानते हुए कि आप कभी भी अंतर्राष्ट्रीयकरण नहीं करते हैं)। आपकी आवश्यकता जो कहती है कि दो वर्ण वाले देश कोड को काट देना "शालीन" बात है, पागल है। आप जानते हैं कि एक त्रुटि थी, काट-छाँट और स्वीकार न करें। यदि आप काटते हैं तो एक उच्च उच्च संभावना है कि आप एक गलत देश कोड के साथ समाप्त हो जाएंगे।
कोडरजॉ

अधिकांश अनुप्रयोगों में डेटा सत्यापन डेटाबेस में भेजने से पहले किया जाएगा ...
3

2
ज़रूर। अधिकांश। लेकिन मुझे लगता है कि यहां आप मान रहे हैं कि एक डेवलपर जो मौजूदा डेटाबेस के लिए एक नया एप्लिकेशन विकसित कर रहा है, वह डेटा पर प्रतिबंधों से अवगत है (हम हर प्रकार के डेटा पर सभी विशेषज्ञ नहीं हैं और यह हर डेटाबेस में कैसे लागू होता है? )। सिर्फ इसलिए कि आप अपने आवेदन में डेटा को मान्य कर सकते हैं इसका मतलब यह नहीं है कि आपने किया था।
shufler

3
the design documentation (which surely exists)हा। : डी
कैमिलो मार्टिन

14

मैं तुम्हारे साथ हूँ। विस्तार से ध्यान देने योग्य ध्यान गर्दन में दर्द है और इसका सीमित मूल्य है।

एक बार, डिस्क एक कीमती वस्तु थी और हम इसे अनुकूलित करने के लिए गोलियों का इस्तेमाल करते थे। भंडारण की कीमत 1,000 के कारक से गिर गई है, जिससे प्रत्येक बाइट को कम मूल्यवान बनाने में लगने वाला समय कम हो जाता है।

यदि आप केवल CHAR फ़ील्ड का उपयोग करते हैं, तो आप निश्चित लंबाई वाली पंक्तियाँ प्राप्त कर सकते हैं। यदि आप फ़ील्ड के लिए सटीक आकार चुनते हैं, तो यह कुछ डिस्क को वास्तविक रूप से सहेज सकता है। आपको अधिक घनत्व वाले डेटा (कम आई / ओ के लिए टेबल स्कैन) और तेज़ अपडेट (अपडेट और आवेषण के लिए एक ब्लॉक में खुली जगहों का पता लगाने में आसान) मिल सकता है।

हालाँकि, यदि आप अपने आकारों का अनुमान लगाते हैं, या आपके वास्तविक डेटा आकार परिवर्तनशील हैं, तो आप CHAR क्षेत्रों के साथ अंतरिक्ष को बर्बाद कर देंगे। डेटा कम घनी तरह से पैक हो जाएगा (बड़ी पुनर्प्राप्ति के लिए I / O के लिए अग्रणी)।

आम तौर पर, चर क्षेत्रों पर आकार डालने के प्रयास से प्रदर्शन लाभ मामूली होते हैं। यदि आप अंतर को माप सकते हैं, तो यह देखने के लिए कि आप CHAR (x) की तुलना में VARCHAR (255) का उपयोग करके आसानी से बेंचमार्क कर सकते हैं।

हालांकि, कभी-कभी, मुझे "छोटा", "मध्यम", "बड़ा" संकेत प्रदान करने की आवश्यकता होती है। इसलिए मैं आकारों के लिए 16, 64 और 255 का उपयोग करता हूं।


13

आजकल, मैं कल्पना नहीं कर सकता यह वास्तव में किसी भी अधिक मायने रखता है।

चर लंबाई क्षेत्रों का उपयोग करने के लिए एक कम्प्यूटेशनल ओवरहेड है, लेकिन आज सीपीयू की अधिकता के साथ, यह विचार करने योग्य भी नहीं है। I / O प्रणाली इतनी धीमी है कि किसी भी कम्प्यूटेशनल लागत को प्रभावी ढंग से अस्तित्वहीन बनाने के लिए varchars को संभालती है। वास्तव में, एक varchar की कीमत कम्प्यूटेशनल रूप से निश्चित लंबाई के क्षेत्रों में चर लंबाई फ़ील्ड का उपयोग करके सहेजे गए डिस्कस्पेस की मात्रा पर शुद्ध जीत है। आप सबसे अधिक संभावना पंक्ति घनत्व है।

अब, varchar फ़ील्ड्स की जटिलता यह है कि आप आसानी से रिकॉर्ड संख्या के माध्यम से रिकॉर्ड का पता नहीं लगा सकते हैं। जब आपके पास एक निश्चित लंबाई पंक्ति आकार (निश्चित लंबाई फ़ील्ड के साथ) है, तो यह डिस्क ब्लॉक की गणना करने के लिए तुच्छ है जो एक पंक्ति आईडी इंगित करता है। एक चर लंबाई के साथ, इस तरह की खिड़की से बाहर चला जाता है।

तो, अब आपको किसी भी अन्य प्राथमिक कुंजी की तरह, कुछ प्रकार के रिकॉर्ड नंबर इंडेक्स को बनाए रखने की आवश्यकता है, या आपको एक मजबूत पंक्ति पहचानकर्ता बनाने की आवश्यकता है जो पहचानकर्ता को विवरण (जैसे ब्लॉक, आदि) को एन्कोड करता है। यदि आप ऐसा करते हैं, हालांकि, यदि पंक्ति को लगातार भंडारण पर स्थानांतरित किया जाता है, तो आईडी को पुनर्गणना करना होगा। कोई बड़ी बात नहीं है, बस इंडेक्स प्रविष्टियों के सभी को फिर से लिखना और यह सुनिश्चित करना है कि आप या तो क) कभी भी इसे उपभोक्ता के सामने उजागर न करें या बी) कभी भी यह दावा नहीं करें कि संख्या विश्वसनीय है।

लेकिन जब से हमारे पास आज के संस्करण हैं, तो varchar (255) से अधिक varchar (16) का एकमात्र मूल्य यह है कि DB, varchar (16) पर 16 वर्ण सीमा को लागू करेगा। यदि DB मॉडल वास्तव में भौतिक डेटा मॉडल का प्रतिनिधि माना जाता है, तो फ़ील्ड लंबाई होने का महत्व हो सकता है। यदि, हालांकि, यह "मॉडल और स्टोरेज" के बजाय केवल "स्टोरेज" है, तो कोई जरूरत नहीं है।

फिर आपको बस एक पाठ क्षेत्र के बीच विचार करने की आवश्यकता है जो कि अनुक्रमणीय (जैसे कि चरचर) बनाम कुछ ऐसा है जो (पाठ या CLOB क्षेत्र की तरह) नहीं है। इंडेक्सबल फ़ील्ड्स इंडेक्स को सुविधाजनक बनाने के लिए आकार की एक सीमा रखते हैं जबकि CLOB फ़ील्ड्स (कारण के भीतर) नहीं होती हैं।


5

मेरे अनुभव में, यदि आप 255 वर्णों के डेटाटाइप की अनुमति देते हैं, तो कुछ बेवकूफ उपयोगकर्ता (या कुछ अनुभवी परीक्षक) वास्तव में इसे भर देंगे।

फिर आपके पास सभी प्रकार की समस्याएं हैं, जिसमें आप अपने आवेदन में उन क्षेत्रों को रिपोर्ट और ऑन-स्क्रीन डिस्प्ले में कितनी जगह की अनुमति देते हैं। अपने डेटाबेस में डेटा के लिए प्रति-पंक्ति सीमा से अधिक होने की संभावना का उल्लेख नहीं करने के लिए (यदि आपके पास इन 255 वर्ण क्षेत्रों में से कुछ से अधिक था)।

शुरुआत में एक उचित सीमा लेने के लिए बहुत आसान है, फिर आवेदन और डेटाबेस के माध्यम से इसे लागू करें।


0

अपनी जरूरत के हिसाब से थोड़ा-थोड़ा आवंटित करना अच्छा है। फोन नंबर कभी भी बड़े नहीं होंगे।

एक कारण यह है कि जब तक आप बड़ी प्रविष्टियों के खिलाफ मान्य नहीं करते, कोई भी संदेह नहीं है कि कोई भी सभी का उपयोग करेगा। तब आप अपनी पंक्ति में जगह छोड़ सकते हैं। मुझे MySQL सीमा के बारे में निश्चित नहीं है, लेकिन 8060 MS SQL में अधिकतम पंक्तियाँ हैं।

एक अधिक सामान्य डिफ़ॉल्ट 50 imho होगा, और फिर जहां आवश्यकता होती है उसे बढ़ाएं।


धन्यवाद। मैं निश्चित रूप से इसके बारे में सहमत हूं कि यह अच्छा अभ्यास है। यह प्रदर्शन का पहलू है जिसे मैं वास्तव में स्पष्टीकरण चाहूंगा
Olly

0

एक mysql संदर्भ में यह महत्वपूर्ण हो सकता है जब कहा varchar कॉलम पर अनुक्रमित के साथ काम कर रहे हैं, क्योंकि mysql में अधिकतम है। सूचकांक-पंक्ति प्रति 767bytes की सीमा।

इसका मतलब यह है कि जब कई वर्जन 255 कॉलम में एक इंडेक्स जोड़ते हैं, तो आप इस सीमा तक प्राप्त कर सकते हैं / बल्कि utf8 या utf8mb4 कॉलम पर भी तेजी से ऊपर दिए गए उत्तरों के अनुसार।

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