2013-04-15 9 views
7

डेटाबेस तालिका डिज़ाइन - लंबे या चौड़े के लिए अधिक कुशल (क्वेरी प्रदर्शन के संदर्भ में) क्या अधिक कुशल है?MySQL: लांग टेबल बनाम विस्तृत तालिका

Ie, इस

id size price 
1 S 12.4 
1 M 23.1 
1 L 33.3 
2 S 3.3 
2 M 5.3 
2 L 11.0 

बनाम इस

id S  M  L 
1 12.4 23.1 33.3 
2 3.3 5.3 11.0 

आम तौर पर (मुझे लगता है) यह GROUP BY के बीच प्रदर्शन की तुलना करने के लिए नीचे आता है और सीधे स्तंभों का चयन:

SELECT AVG(price) FROM table GROUP BY size 

या

SELECT AVG(S), AVG(M), AVG(L) FROM table 

दूसरा लिखने के लिए थोड़ा लंबा समय है (कई स्तंभों के संदर्भ में), लेकिन दोनों के प्रदर्शन के बारे में क्या? यदि संभव हो, तो इन तालिका प्रारूपों में से प्रत्येक के सामान्य फायदे/नुकसान क्या हैं?

उत्तर

5

सबसे पहले, ये विभिन्न उद्देश्यों के लिए उपयुक्त दो अलग-अलग डेटा मॉडल हैं।

कहा जा रहा है, मैं उम्मीद थी दूसरे मॉडल तेजी से एकत्रीकरण के लिए, बस क्योंकि डेटा अधिक दृढ़तापूर्वक पैक किया जाता है, इसलिए जरूरत के कम आई/ओ हो जाएगा: में

  • ग्रुप द्वारा पहला मॉडल पूर्ण सूचकांक {size, price} पर स्कैन से संतुष्ट हो सकता है। रैम में फ़िट होने के लिए डेटा बहुत बड़ा होने पर सूचकांक का विकल्प बहुत धीमा है।
  • दूसरे मॉडल में क्वेरी पूर्ण तालिका स्कैन से संतुष्ट हो सकती है। कोई अनुक्रमणिका आवश्यक नहीं ।

चूंकि पहले दृष्टिकोण के लिए टेबल + इंडेक्स की आवश्यकता होती है और दूसरी तालिका केवल तालिका के लिए होती है, तो दूसरे मामले में कैश उपयोग बेहतर होता है।यहां तक ​​कि यदि हम दूसरे मॉडल में तालिका के साथ पहले मॉडल में कैशिंग और इंडेक्स (तालिका के बिना) की तुलना करते हैं, तो मुझे संदेह है कि सूचकांक तालिका से बड़ा होगा, क्योंकि यह भौतिक रूप से size रिकॉर्ड करता है और "छेद" सामान्य उपयोग नहीं करता है बी-पेड़ के लिए (हालांकि तालिका के लिए यह भी सच है यदि यह clustered है)।

और आखिरकार, दूसरे मॉडल में इंडेक्स रखरखाव ओवरहेड नहीं है, जो INSERT/UPDATE/DELETE प्रदर्शन को प्रभावित कर सकता है।

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


लेकिन आप डेटा के प्रतिनिधि राशि पर वास्तव में उपाय सुनिश्चित करने के लिए करना चाहिए।

वहाँ कोई है के बाद से जहां अपने प्रश्न में खंड, सभी पंक्तियों स्कैन किया जाएगा। इंडेक्स केवल तालिका की पंक्तियों का अपेक्षाकृत छोटा सबसेट प्राप्त करने के लिए उपयोगी होते हैं (और कभी-कभी index-only scans के लिए)। अंगूठे के मोटे नियम के रूप में, यदि तालिका में 10% से अधिक पंक्तियों की आवश्यकता होती है, तो इंडेक्स मदद नहीं करेगा और डीबीएमएस अक्सर इंडेक्स उपलब्ध होने पर भी एक पूर्ण टेबल स्कैन का चयन करेगा।

+0

महान स्पष्टीकरण के लिए बहुत बहुत धन्यवाद! अंत में आपकी अतिरिक्त टिप्पणियां बहुत उपयोगी हैं, मेरा प्रश्न सिर्फ एक बड़ी समस्या का एक संक्षिप्त सारांश है जिसका सामना मैं कर रहा हूं और मैं निश्चित रूप से इन बारीकी से विचार करूंगा। – sashkello

1

लंबे समय तक उपयोग में अधिक लचीला है। यह आप उदाहरण

SELECT MAX(price) where size='L' 

यह भी size पर और id पर अनुक्रमण के लिए अनुमति देता है के लिए size पर फिल्टर करने के लिए अनुमति देता है। यह GROUP BY को गति देता है और कोई भी प्रश्न जहां अन्य तालिका id और/या size ऐसी उत्पाद स्टॉक तालिका पर शामिल हो जाती है।

2

पहला विकल्प अधिक पंक्तियों में परिणाम देता है और आमतौर पर दूसरे विकल्प की तुलना में धीमा हो जाएगा।

हालांकि, जैसा कि डेल्टालिमा ने भी संकेत दिया था, पहला विकल्प अधिक लचीला है। न केवल जब विभिन्न क्वेरी विकल्पों की बात आती है, लेकिन यदि आपको एक दिन को अन्य आकारों, रंगों आदि के साथ तालिका का विस्तार करने की आवश्यकता होती है तो

जब तक आपके पास बहुत बड़ा डेटासेट नहीं है या अल्ट्रा-फास्ट लुकअप समय की आवश्यकता नहीं है, तो आप शायद पहले विकल्प के साथ बेहतर हो जाएगा।

यदि आपके पास बहुत बड़ा डेटासेट है या इसकी आवश्यकता है, तो आप पूर्व-गणना वाले सारांश मानों के साथ एक तालिका बनाने से बेहतर हो सकते हैं।

संबंधित मुद्दे