SQL चयन गति int बनाम varchar


110

मैं एक तालिका बनाने की प्रक्रिया में हूं और इसने मुझे आश्चर्यचकित कर दिया है।

अगर मैं स्टोर करता हूं, तो कारों को एक मेक (एफएक्स बीएमडब्लू, ऑडी एक्ट।) कहते हैं, अगर मैं मेक को एक इंट या वर्चर के रूप में संग्रहीत करता हूं, तो क्या यह क्वेरी की गति पर कोई फर्क पड़ेगा।

तो है

SELECT * FROM table WHERE make = 5 AND ...;

की तुलना में तेज़ / धीमा

SELECT * FROM table WHERE make = 'audi' AND ...;

या गति कमोबेश एक जैसी होगी?

जवाबों:


99

इंट की तुलना वर्चर्स की तुलना में तेजी से होती है, साधारण तथ्य के लिए कि चींटियों को वार्चर की तुलना में बहुत कम जगह मिलती है।

यह अनइंडैक्स और इंडेक्सेड एक्सेस के लिए सही है। जाने का सबसे तेज़ तरीका एक अनुक्रमित इंट कॉलम है।


जैसा कि मैंने देखा है कि आपने प्रश्न पोस्टग्रेकल को टैग किया है, आप विभिन्न तिथि प्रकारों के अंतरिक्ष उपयोग में रुचि रख सकते हैं:


13
आप पीजी 7.4 का जिक्र कर रहे हैं। आधुनिक संस्करणों में, यदि आपके पास <126 बाइट्स हैं, तो वे 1byte + लंबाई लेते हैं। यह भी ध्यान दें कि कारण के तार बहुत धीमे होते हैं अक्सर यह होता है कि टक्कर-संवेदी तुलना बेहद महंगी होती है - यह नहीं कि स्ट्रिंग अधिक स्थान लेती है। लेकिन अंतिम परिणाम समान है, बिल्कुल।
मैग्नस हैगर

@ मैग्नस - हेड-अप के लिए धन्यवाद। मेरे उत्तर को संपादित करने के लिए स्वतंत्र महसूस करें क्योंकि मुझे लगता है कि आपके पास पर्याप्त प्रतिनिधि हैं।
रॉबर्ट मुंटेनू

"ऐसा नहीं है कि स्ट्रिंग अधिक स्थान लेता है" ... न्यूनतम आकार से ऊपर के वर्णों के तार उच्च-सटीक संख्याओं की तुलना में बहुत अधिक स्थान की एक ऊँचाई तक ले जाते हैं, क्योंकि एक संख्या (एकवचन) की एक निश्चित इकाई होती है, तार हमेशा कुल प्रकार होते हैं । एक स्ट्रिंग में 64-बिट संख्या 4 बाइट्स प्रति-वर्ण के लिए 8 बाइट्स, जिसमें लंबाई बाइट या संरचना भी शामिल है; या अविश्वसनीय रूप से भोली कार्यान्वयन के लिए एक और टर्मिनेटर चरित्र ...
MrMesees

@RobertMunteanu हे रॉबर्ट, क्षमा याचना मुझे पता है कि यह एक पुरानी पोस्ट है लेकिन क्या मैं निम्नलिखित पर ... कृपया जांच कर सकता हूं: पूर्णांक क्वेरी करने के लिए, मुझे प्रत्येक स्ट्रिंग कॉलम को अन्य तालिका (संबंध) से लिंक करना होगा। हालाँकि, इसका मतलब है कि प्रत्येक क्वेरी के लिए अधिक ज्वाइनिंग ऑपरेशन आवश्यक हैं। मैं यह कैसे निर्धारित करूं कि यह व्यापार बंद है? धन्यवाद!
ऐरीफाइएड

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

36

कुछ मोटे बेंचमार्क:

Postgres में 4 मिलियन रिकॉर्ड 9.x

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

8 जीबी रैम, आई 7, एसएसडी लैपटॉप पर परिणाम:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

तो यह इस सेटअप के लिए जैसा दिखता है, जब तक कि आपके इंडेक्स रैम में फिट होते हैं, बिगिंट बनाम 16-चार टेक्स्ट की गति में कोई फर्क नहीं पड़ता है।


6
बहुत ही रोचक। अंतर नगण्य कैसे आया?
चिबूजे ओपटा

18

यह एक varchar के बजाय एक int का उपयोग करके थोड़ा तेज होगा। गति के लिए अधिक महत्वपूर्ण उस क्षेत्र पर एक सूचकांक होना है जिसे क्वेरी रिकॉर्ड खोजने के लिए उपयोग कर सकती है।

इंट का उपयोग करने का एक और कारण है, और वह है डेटाबेस को सामान्य करना। टेबल में हजारों बार संग्रहित 'मर्सिडीज-बेंज' के पाठ के बजाय, आपको इसे आईडी स्टोर करना चाहिए और ब्रांड नाम एक अलग तालिका में एक बार संग्रहीत करना चाहिए।


आप और समझा सकते हैं? क्या आपका मतलब Mercedes-Benzहजारों बार आईडी स्टोर करने के बजाय है 1। उदाहरण के लिए तालिका car_brands, कॉलम Brandsऔर Id। पंक्ति Mercedes-Benzऔर 1। और मुख्य तालिका कॉलम Brandsऔर मूल्य में 1। और जब SELECT, तब पहली बार Idतालिका से car_brandsऔर फिर SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz)। या कुछ और दृष्टिकोण?
एंड्रीस

3
@ user2118559: हां, यह है कि आप इसे कैसे स्टोर करेंगे। डेटा प्राप्त करने के लिए आप आमतौर पर एक उपकुंजी के बजाय एक जुड़ाव का उपयोग करेंगे select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz':।
गुफ़ा

क्यों होता है पतन? यदि आप यह नहीं समझाते हैं कि ऐसा क्या है जो आपको लगता है कि यह गलत है, तो इससे उत्तर में सुधार नहीं हो सकता है।
गुफ़ा

8

स्ट्रिंग तुलना बनाम गैर-फ़्लोट्स के वास्तविक प्रदर्शन के लिए टूटना, इस मामले में किसी भी आकार के बिना हस्ताक्षर किए और कोई फर्क नहीं पड़ता। आकार वास्तव में प्रदर्शन में सही अंतर है। यह 1byte + (126bytes तक) बनाम 1,2,4 या 8 बाइट तुलना करें ... जाहिर है कि गैर-फ्लोट स्ट्रिंग्स और फ्लोट्स की तुलना में छोटे होते हैं, और इस प्रकार विधानसभा में अधिक सीपीयू अनुकूल होते हैं।

सभी भाषाओं में स्ट्रिंग की तुलना स्ट्रिंग से कुछ धीमी है, जिसकी तुलना सीपीयू द्वारा 1 निर्देश में की जा सकती है। यहां तक ​​कि एक 32 बिट सीपीयू पर 8 बाइट (64 बिट) की तुलना करना अभी भी एक वराहार (2) या उससे बड़ा है। * फिर से, उत्पादित असेंबली (यहां तक ​​कि हाथ से देखें) में चार से बाइट सीपीयू संख्यात्मक द्वारा चार की तुलना में अधिक निर्देश लगते हैं।

अब, कितना तेज? डेटा की मात्रा पर भी निर्भर करता है। यदि आप बस 5 की तुलना 'ऑडी' से कर रहे हैं - और वह सब आपके डीबी के पास है, तो परिणामी अंतर इतना न्यूनतम है कि आप इसे कभी नहीं देख पाएंगे। सीपीयू, कार्यान्वयन (क्लाइंट / सर्वर, वेब / स्क्रिप्ट, आदि) के आधार पर आप शायद इसे तब तक नहीं देखेंगे जब तक कि आप डीबी सर्वर पर कुछ सौ तुलनाओं को हिट नहीं करते हैं (शायद यह ध्यान देने योग्य होने से पहले कुछ हजार तुलना भी करता है)।

  • हैश तुलनाओं के बारे में गलत विवाद को शून्य करना। अधिकांश हैशिंग एल्गोरिदम स्वयं धीमे होते हैं, इसलिए आपको CRC64 और छोटे जैसी चीजों से लाभ नहीं होता है। 12 से अधिक वर्षों के लिए मैंने मल्टी-काउंटी खोज इंजन के लिए खोज एल्गोरिदम और क्रेडिट ब्यूरो के लिए 7 साल विकसित किए। कुछ भी आप तेजी से संख्यात्मक में रख सकते हैं ... उदाहरण के लिए फोन नंबर, ज़िप कोड, यहां तक ​​कि मुद्रा * 1000 (भंडारण) मुद्रा div 1000 (पुनर्प्राप्ति) तुलनाओं के लिए DECIMAL से तेज है।

Ozz


6

सूचकांक या नहीं, int बहुत तेज़ है (लंबे समय तक चलने वाला, इसे धीमा करने वाला)।

एक और कारण: varchar क्षेत्र पर सूचकांक int की तुलना में बहुत बड़ा होगा। बड़ी मेज के लिए इसका मतलब सैकड़ों मेगाबाइट (और हजारों पेज) हो सकता है। यह प्रदर्शन को बहुत खराब करता है क्योंकि अकेले सूचकांक को पढ़ने के लिए कई डिस्क रीड की आवश्यकता होती है।


3
"ऑडी" के 5 लाख रिकॉर्ड के उदाहरण के लिए, क्या इंडेक्स केवल "ऑडी" के स्ट्रिंग की एक प्रति और प्राइमरी_की के 5 मिलियन पूर्णांक नहीं रखेगा? क्या आकार अंतर वास्तव में इतना बड़ा होगा, यह vchar या पूर्णांक होगा?
लुललाला

आप सही लूलाला हैं लेकिन एक ऐसे कॉलम के लिए जिसमें रैंडम स्ट्रिंग्स सम्‍मिलित होने जा रहे हैं जिसका जवाब काफी हद तक सही है।
फवाद

4

सामान्य तौर पर इंट तेजी से होगा। अब चरचर को यह धीमा मिलता है


3

संकेत: क्षेत्र के लिए संभावित मान हैं मेकअप होगा कभी नहीं (या शायद ही कभी) बदलती है तो आप Enum एक समझौता के रूप में उपयोग कर सकते हैं। यह अच्छी पठनीयता के साथ अच्छी गति को जोड़ती है।


1
दिलचस्प है, ENUM और int के बीच गति अंतर कैसे होगा?
googletorp

क्या PostgresSQL के पास enumडेटा प्रकार है? हालांकि मैं यह MySQL विशिष्ट था।
रॉबर्ट मुंटेनू

Postgres में ENUM है, लेकिन मुझे नहीं लगता कि यह MySQL के समान ही लागू किया गया है। postgresql.org/docs/current/static/datatype-enum.html
googletorp

2
प्रदर्शन के लिहाज से, ENUM को खोज क्षेत्र में int के समान ही कम या ज्यादा प्रदर्शन करना चाहिए, लेकिन लक्ष्य सूची में varchar के रूप में (क्योंकि यह मिलान किए गए पंक्तियों के लिए क्लाइंट को पूरे स्ट्रिंग को स्थानांतरित करना है, न कि केवल इंट को)
Magnus Hagander

1
यहाँ एक दिलचस्प पढ़ा : क्यों MySQL में enum उपयोग करने के लिए नहीं पर (डी बस आग करने के लिए कुछ ईंधन जोड़ने के लिए)
विल्ट

1

यदि आप दोनों क्षेत्रों में से किसी एक को अनुक्रमित करते हैं, तो यह तेज़ होगा। अपने प्रश्न के लिए, मुझे लगता intहै कि की तुलना में तेज है varchar


0

कुछ हद तक रिश्तेदार। हां, INT तेज होगा, लेकिन सवाल यह है कि क्या यह आपकी स्थिति में ध्यान देने योग्य है। क्या VARCHARs सिर्फ कुछ छोटे शब्द हैं, या लंबे ग्रंथ हैं? और तालिका में कितनी पंक्तियाँ हैं? अगर कुछ पंक्तियाँ हैं, तो यह संभवतः पूरी तरह से स्मृति में बफ़र किया जाएगा (जब अक्सर अनुरोध किया जाता है), उस स्थिति में आप बहुत अंतर नोटिस नहीं करेंगे। फिर निश्चित रूप से अनुक्रमण होता है, जो तालिका बढ़ने पर अधिक महत्वपूर्ण हो जाता है। SSD का उपयोग तेज हो सकता है तो HD अनुकूलित प्रश्नों के साथ हो सकता है। साथ ही अच्छे डिस्क-नियंत्रक कभी-कभी प्रश्नों को गति देते हैं> 10x। यह सिर्फ VARCHAR का उपयोग करने के लिए जगह छोड़ सकता है जो पढ़ने और लिखने के प्रश्नों को आसान बनाता है (जटिल जुड़ाव लिखने की आवश्यकता नहीं है) और विकास को गति देता है। हालांकि शुद्धतावादी असहमत होंगे और हमेशा सब कुछ सामान्य करेंगे।

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