अनुक्रमित: पूर्णांक बनाम स्ट्रिंग प्रदर्शन यदि नोड्स की संख्या समान है


26

मैं PostgreSQL (9.4) डेटाबेस के साथ रूबी ऑन रेल्स में एक एप्लिकेशन विकसित कर रहा हूं। मेरे उपयोग के मामले में, तालिकाओं में स्तंभों को बहुत बार देखा जाएगा, क्योंकि आवेदन का पूरा बिंदु एक मॉडल पर बहुत विशिष्ट विशेषताओं की खोज कर रहा है।

मैं वर्तमान में यह तय कर रहा हूं कि स्तंभों के लिए एक integerप्रकार का उपयोग करें या बस एक विशिष्ट स्ट्रिंग प्रकार (जैसे character varying(255), जो रेल में डिफ़ॉल्ट है ) का उपयोग करें, क्योंकि मुझे यकीन नहीं है कि प्रदर्शन अंतर सूचकांक पर क्या होगा।

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

हालाँकि, जो स्ट्रिंग अनुक्रमित किया जाएगा, वह लगभग 20 वर्ण लंबा हो सकता है, जो कि मेमोरी में लगभग 5x होता है जो पूर्णांक का होता है (यदि पूर्णांक 4 बाइट्स है, और तार 1 बाइट प्रति वर्ण पर शुद्ध ASCII हैं, तो यह है)। मुझे नहीं पता है कि डेटाबेस इंजन इंडेक्स लुक-अप कैसे करते हैं, लेकिन अगर यह स्ट्रिंग को "स्कैन" करने की आवश्यकता है जब तक कि यह बिल्कुल मेल नहीं खाता है , तो संक्षेप में इसका मतलब है कि स्ट्रिंग लुकअप पूर्णांक लुकअप की तुलना में 5x धीमा होगा; "स्कैन" जब तक पूर्णांक लुकअप के लिए मिलान 20 के बजाय 4 बाइट होगा। यह वही है जो मैं कल्पना कर रहा हूं:

लुकअप मान है (पूर्णांक) 4:

स्कैनिंग ............................ FOUND | रिकॉर्ड प्राप्त कर रहा है ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | BYTE_8 | ...

लुकअप मान (स्ट्रिंग) "some_val" (8 बाइट्स) है:

स्कैनिंग ................................................. ……………………………… FOUND | रिकॉर्ड प्राप्त कर रहा है ... | BYTE_1 | BYTE_2 | BYTE_3 | BYTE_4 | BYTE_5 | BYTE_6 | BYTE_7 | BYTE_8 | BYTE_8 | ...

मुझे उम्मीद है कि यह समझ में आता है। मूल रूप से, क्योंकि पूर्णांक कम जगह लेता है, यह उसके स्ट्रिंग समकक्ष की तुलना में "तेजी से मिलान" किया जा सकता है। शायद यह पूरी तरह से गलत अनुमान है, लेकिन मैं कोई विशेषज्ञ नहीं हूं, इसलिए मैं आप लोगों से पूछ रहा हूं! मुझे लगता है कि यह जवाब जो मुझे मिला है वह मेरी परिकल्पना का समर्थन करता है, लेकिन मैं निश्चित होना चाहता हूं।

कॉलम में संभावित मानों में से किसी एक का उपयोग करने में परिवर्तन नहीं होगा, इसलिए सूचकांक स्वयं नहीं बदलेगा (जब तक कि मैंने एनम के लिए एक नया मूल्य नहीं जोड़ा है)। इस मामले में, वहाँ का उपयोग करने में एक प्रदर्शन अंतर हो जाएगा integerया varchar(255), या एक पूर्णांक प्रकार का उपयोग करता है और अधिक समझ बनाने?


मैं जो कारण पूछ रहा हूं, वह यह है कि रेल का enumप्रकार स्ट्रिंग कुंजियों के लिए पूर्णांक बनाता है, लेकिन वे उपयोगकर्ता-सामना करने वाले कॉलम नहीं हैं। अनिवार्य रूप से, आप सत्यापन नहीं कर सकते हैं कि एनम मूल्य एक मान्य है, क्योंकि ArgumentErrorकिसी भी मान्यताओं को चलाने से पहले एक अमान्य मूल्य का कारण होगा । किसी stringप्रकार का उपयोग करने से सत्यापन की अनुमति मिलती है, लेकिन यदि प्रदर्शन लागत है तो मैं सत्यापन समस्या के आसपास ही हैक कर लूंगा।

जवाबों:


32

संक्षिप्त उत्तर: हर पहलू integerसे varcharया उससे अधिक तेज़ है text। छोटी मेज और / या छोटी कुंजी के लिए ज्यादा मायने नहीं रखेगा। अंतर कुंजियों की लंबाई और पंक्तियों की संख्या के साथ बढ़ता है।

स्ट्रिंग ... 20 वर्ण लंबा, जो स्मृति में लगभग 5x पूर्णांक का है (यदि एक पूर्णांक 4 बाइट्स है, और तार 1 बाइट प्रति वर्ण पर शुद्ध ASCII हैं, तो यह है)

सटीक होने के लिए, वर्ण प्रकार ( textया varchar) डिस्क पर 20 ASCII वर्णों के लिए 21 बाइट्स पर कब्जा कर लेता है और रैम में 23 बाइट्स। विस्तृत मूल्यांकन:

इसके अलावा महत्वपूर्ण: COLLATIONनियम वर्ण डेटा को अधिक महंगा बना सकते हैं - संख्यात्मक डेटा प्रकारों के विपरीत:

सूचकांक आकार संभवतः ज्यादातर मामलों में प्रदर्शन अंतर के शेर के हिस्से के लिए जिम्मेदार है। इंडेक्स ट्यूपल प्रति ओवरहेड पर विचार करें (मूल रूप से एक टेबल के लिए समान): आइटम पॉइंटर के लिए 4 बाइट्स और टपल हेडर के लिए 24 बाइट्स । इसलिए सूचकांक टपल के लिए 36 बाइट्स ( संरेखण पैडिंग के 4 बाइट्स सहित ) की integerराशि होगी और 20 एएससीआईआई पात्रों के साथ यह 52 बाइट्स (साथ ही इंक पेडिंग) होगा। विवरण:varchar(20)

एक तरफ सभी सिद्धांत: यह सिर्फ परीक्षण के लिए सबसे अच्छा है:

9.5 पोस्टग्रेट्स ने वर्ण डेटा के लंबे तारों को छांटने के लिए एक अनुकूलन पेश किया (कुंजी शब्द "संक्षिप्त कुंजी" )। लेकिन लिनक्स पर कुछ सी लाइब्रेरी फ़ंक्शंस में एक बग ने पोस्टग्रेज 9.5.2 में गैर-सी collations के लिए सुविधा को अक्षम करने के लिए परियोजना को मजबूर किया। जारी नोटों में विवरण।

हालाँकि, यदि आप वास्तव में पोस्टग्रैस enumप्रकारों का उपयोग करते हैं, तो इनमें से अधिकांश विचार अप्रासंगिक हैं, क्योंकि इन्हें integerवैसे भी आंतरिक रूप से मूल्यों के साथ लागू किया जाता है। नियम पुस्तिका:

एक enumमान डिस्क पर चार बाइट्स रखता है।

एक तरफ: varchar(255)SQL सर्वर के शुरुआती संस्करणों के लिए समझ में आता है, जो 255 अक्षरों की सीमा तक आंतरिक रूप से अधिक कुशल डेटा प्रकार का उपयोग कर सकता है। लेकिन 255 वर्णों की विषम लंबाई प्रतिबंध का Postgres में प्रदर्शन पर कोई विशेष प्रभाव नहीं है।


1
varchar(255)बनाम उदाहरण के लिए SQL सर्वर में कोई छुपी हुई अनुकूलन नहीं है varchar(260)। SQL Server 6.x के साथ ऐसा कुछ हो सकता है लेकिन यह लंबे समय तक सही नहीं है।
— a_horse_with_no_name

@a_horse_with_no_name: धन्यवाद, मैंने तदनुसार स्पष्ट किया।
— इरविन ब्रान्डेसटेटर

इसे स्वीकार करने में इतना समय
— लगने के

क्या यह उत्तर पोस्टग्रेज 10 के लिए अभी भी मान्य है?
— मैटी

1
@ माटी: फिर भी मान्य। और मुझे अभी तक पीजी 11 के लिए कुछ भी बदलते नहीं दिख रहा है।
— इरविन ब्रान्डेसटेटर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.