क्वेरी के दौरान डिस्क से क्या पुनर्प्राप्त किया जाता है?


14

बहुत सरल प्रश्न, शायद कहीं उत्तर दिया गया है, लेकिन मैं Google के लिए सही खोज प्रश्न नहीं बना सकता ...

क्या किसी विशेष तालिका में स्तंभों की संख्या उस तालिका के सबसेट पर क्वेरी करते समय किसी क्वेरी के प्रदर्शन को प्रभावित करती है?

उदाहरण के लिए, यदि तालिका फू में 20 कॉलम हैं, लेकिन मेरी क्वेरी केवल उन कॉलमों में से 5 का चयन करती है, तो क्या 20 (बनाम, 10) कॉलम होने से क्वेरी का प्रदर्शन प्रभावित होता है? सादगी के लिए मान लें कि WHERE क्लॉज़ में कुछ भी उन 5 कॉलम में शामिल है।

मैं ऑपरेटिंग सिस्टम के डिस्क कैश के अलावा पोस्टग्रेज के बफर कैश के उपयोग के बारे में चिंतित हूं। मुझे पोस्टग्रेज के फिजिकल स्टोरेज डिज़ाइन की बहुत कम समझ है। टेबल्स को कई पृष्ठों में संग्रहीत किया जाता है (प्रति पृष्ठ 8k आकार में डिफ़ॉल्ट), लेकिन मुझे यह समझ में नहीं आता है कि वहाँ से ट्यूपल्स कैसे व्यवस्थित किए जाते हैं। क्या पीजी स्मार्ट केवल उन 5 कॉलमों को शामिल करने वाले डेटा को डिस्क से लाने के लिए पर्याप्त है?


आप 50 बाइट लाने की बात कर रहे हैं, लेकिन शेष 150 की नहीं। आपकी डिस्क संभवतः इससे भी बड़ी वृद्धि में पढ़ती है!
एंडोमर

आप उन नंबरों को कहां से प्राप्त कर रहे हैं?
Jmoney38

जवाबों:


15

डेटाबेस पेज लेआउट में डॉक्स में पंक्तियों के लिए भौतिक भंडारण का वर्णन किया गया है । एक ही पंक्ति के लिए स्तंभ की सामग्री सभी एक ही डिस्क पृष्ठ में संग्रहीत की जाती है, जिसमें TOAST की एड सामग्री (पृष्ठ में फिट होने के लिए बहुत बड़ी) के उल्लेखनीय अपवाद हैं। प्रत्येक पंक्ति के भीतर क्रमिक रूप से सामग्री निकाली जाती है, जैसा कि समझाया गया है:

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

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

अब TOAST मामला: जब एक व्यक्तिगत क्षेत्र ~ 2kB से अधिक हो जाता है, तो इंजन फ़ील्ड सामग्री को एक अलग भौतिक तालिका में संग्रहीत करता है। जब पूरी पंक्ति एक पृष्ठ (डिफ़ॉल्ट रूप से 8kB) में फिट नहीं होती है, तो यह भी खेल में आता है: कुछ फ़ील्ड TOAST संग्रहण में ले जाए जाते हैं। डॉक्टर कहते हैं:

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

जब वे स्पष्ट रूप से आवश्यक नहीं होते हैं, तो टोस्ट की गई सामग्री को नहीं लाया जाता है, इसलिए लाने के लिए पृष्ठों की कुल संख्या पर उनका प्रभाव छोटा होता है (प्रति कॉलम कुछ बाइट्स)। यह @ dezso के उत्तर में परिणाम बताते हैं।

जैसा कि लिखा गया है, इसके सभी स्तंभों के साथ प्रत्येक पंक्ति पूरी तरह से प्रत्येक अद्यतन पर फिर से लिखी गई है, कोई फर्क नहीं पड़ता कि क्या कॉलम बदले जाते हैं। इसलिए अधिक कॉलम होना जाहिर तौर पर लिखने के लिए अधिक महंगा है।


यह एक किक-गधा जवाब है। बिल्कुल वही, जिसकी मुझे तलाश है। धन्यवाद।
Jmoney38

1
एक अच्छा संसाधन मैं पंक्ति संरचना (pageinspect, और कुछ नमूना उपयोग) के संबंध में पाया यहाँ
Jmoney38

10

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

अतिरिक्त कॉलम स्पष्ट रूप से एक पंक्ति कवर को अधिक डिस्क स्थान बनाते हैं, ताकि कम पंक्तियां एक डेटा पेज (डिफ़ॉल्ट रूप से 8 केबी) पर फिट हो सकें । व्यक्तिगत पंक्तियाँ अधिक पृष्ठों में फैली हुई हैं। डेटाबेस इंजन को आम तौर पर पूरे पृष्ठों को लाना होता है, न कि व्यक्तिगत पंक्तियों को । यह बहुत कम मायने रखता है कि क्या व्यक्तिगत पंक्तियाँ कुछ छोटी या बड़ी हैं - जब तक कि एक ही संख्या में पृष्ठों को पढ़ना पड़ता है।

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

आमतौर पर, आप पैच या पंक्तियों के समूह प्राप्त करेंगे जो अनुक्रम या निकटता में दर्ज किए गए हैं और डेटा पृष्ठ साझा करते हैं। अव्यवस्था के कारण उन पंक्तियों को फैलाया जाता है, आपकी क्वेरी को संतुष्ट करने के लिए अधिक डिस्क पृष्ठों को पढ़ना होगा। अधिक पृष्ठों को पढ़ना आमतौर पर किसी क्वेरी के धीमे होने का सबसे महत्वपूर्ण कारण है । और यह सबसे महत्वपूर्ण कारक है कि अप्रासंगिक कॉलम आपके प्रश्नों को धीमा क्यों बनाते हैं।

बड़े डेटाबेस के साथ, आमतौर पर कैश मेमोरी में सभी को रखने के लिए पर्याप्त रैम नहीं होती है। बड़ी पंक्तियों में अधिक कैश, अधिक विवाद, कम कैश हिट, अधिक डिस्क I / O हैं। और डिस्क रीड आमतौर पर बहुत अधिक महंगे हैं। SSDs के साथ कम, लेकिन पर्याप्त अंतर बना हुआ है। यह पृष्ठ के बारे में उपरोक्त बिंदु पर जोड़ता है।

यह हो सकता है या नहीं हो सकता है कोई फर्क अगर अप्रासंगिक कॉलम टोस्ट एड कर रहे हैं। प्रासंगिक कॉलम टोस्ट-एड भी हो सकते हैं, जिससे एक ही प्रभाव वापस आ सकता है।


1

एक छोटा परीक्षण:

CREATE TABLE test2 (
    id serial PRIMARY KEY,
    num integer,
    short_text varchar(32),
    longer_text varchar(1000),
    long_long_text text
);

INSERT INTO test2 (num, short_text, longer_text, long_long_text)
SELECT i, lpad('', 32, 'abcdefeghji'), lpad('', 1000, 'abcdefeghji'), lpad('', (random() * 10000)::integer, 'abcdefeghji')
FROM generate_series(1, 10000) a(i);

ANALYZE test2;

SELECT * FROM test2;
[...]
Time: 1091.331 ms

SELECT num FROM test2;
[...]
Time: 21.310 ms

क्वेरी को पहले 250 पंक्तियों ( WHERE num <= 250) में परिणाम क्रमशः 34.539 एमएस और 8.343 एमएस में सीमित करना। long_long_textइस सीमित सेट के परिणाम से 18.432 एमएस में सभी का चयन करना । इससे पता चलता है कि आपकी शर्तों में पीजी काफी स्मार्ट है।


खैर, मैं निश्चित रूप से इनपुट की सराहना करता हूं। हालाँकि, मैं यह निश्चितता के साथ नहीं कह सकता कि यह परीक्षण परिदृश्य साबित करता है कि मैंने मूल रूप से क्या प्रस्तावित किया था। कुछ मुद्दे हैं। एक के लिए, जब आप पहली बार "SELECT * FROM test2" चलाते हैं, तो आपको अपना साझा बफर कैश भरना चाहिए। उस क्वेरी को डिस्क से पुनर्प्राप्त करने में अधिक समय लगेगा। इस प्रकार, दूसरी क्वेरी सैद्धांतिक रूप से बहुत तेज़ होती क्योंकि यह एसबी कैश से प्राप्त होती। लेकिन मैं मानता हूं कि यह 'सुझाव' देता है कि पीजी केवल आपके बाद के परीक्षणों / तुलनाओं के आधार पर इसकी ज़रूरत की पंक्तियों को प्राप्त करता है।
Jmoney38

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