MySQL - पंक्तियों की गिनती के लिए गिनती (*) और info_schema.tables का उपयोग करने के बीच अंतर


16

मैं अपनी तालिका में पंक्तियों की संख्या गिनने का एक तेज़ तरीका चाहता हूं जिसमें कई मिलियन पंक्तियाँ हैं। स्टैक ओवरफ्लो पर मुझे पोस्ट " MySQL: Fastest way to count number of row " मिली , जो ऐसा लग रहा था कि यह मेरी समस्या को हल कर देगा। बियुआ ने यह उत्तर दिया:

SELECT
    table_rows "Rows Count"
FROM
    information_schema.tables
WHERE
    table_name="Table_Name"
AND
    table_schema="Database_Name";

जो मुझे पसंद आया क्योंकि यह स्कैन के बजाय एक लुकअप जैसा दिखता है, इसलिए यह तेज़ होना चाहिए, लेकिन मैंने इसके खिलाफ परीक्षण करने का फैसला किया

SELECT COUNT(*) FROM table 

यह देखने के लिए कि प्रदर्शन में कितना अंतर था।

दुर्भाग्य से मुझे नीचे दिखाए गए अनुसार अलग-अलग उत्तर मिल रहे हैं:

यहाँ छवि विवरण दर्ज करें

सवाल

उत्तर लगभग 2 मिलियन पंक्तियों द्वारा भिन्न क्यों हैं? मैं उस क्वेरी का अनुमान लगा रहा हूं जो एक पूर्ण तालिका स्कैन करता है वह अधिक सटीक संख्या है, लेकिन क्या कोई तरीका है जिससे मुझे इस धीमी क्वेरी को चलाने के बिना सही संख्या मिल सकती है?


मैं भाग गया ANALYZE TABLE data_302, जो 0.05 सेकंड में पूरा हुआ। जब मैंने फिर से क्वेरी चलाई, तो मुझे अब 34384599 पंक्तियों का बहुत करीब से परिणाम मिल रहा है, लेकिन यह अभी भी select count(*)34906061 पंक्तियों के समान संख्या नहीं है । क्या टेबल का विश्लेषण तुरंत वापस आता है और पृष्ठभूमि में प्रक्रिया होती है? मुझे लगता है कि यह उल्लेख करने लायक है कि यह एक परीक्षण डेटाबेस है और वर्तमान में इसे लिखा नहीं जा रहा है।

किसी को परवाह नहीं है अगर यह किसी को बताने का मामला है कि तालिका कितनी बड़ी है, लेकिन मैं पंक्ति गिनती को कोड के एक बिट में पास करना चाहता था जो डेटाबेस को क्वेरी करने के लिए "समान आकार" अतुल्यकालिक प्रश्नों को बनाने के लिए उस आकृति का उपयोग करेगा। समानांतर में, सिकंदर रुबिन द्वारा समानांतर क्वेरी निष्पादन के साथ धीमी क्वेरी प्रदर्शन बढ़ाने में दिखाए गए तरीके के समान है । जैसा कि यह है, मैं बस के साथ उच्चतम आईडी प्राप्त करूंगा SELECT id from table_name order by id DESC limit 1और आशा करता हूं कि मेरे टेबल भी खंडित नहीं होंगे।

जवाबों:


23

एक तालिका में पंक्तियों को "गिनने" के विभिन्न तरीके हैं। जो सबसे अच्छा है वह आवश्यकताओं पर निर्भर करता है (गणना की सटीकता, कितनी बार प्रदर्शन किया जाता है, चाहे हमें पूरी तालिका की गणना की आवश्यकता हो या चर whereऔर group byखंड, आदि के साथ)

  • a) सामान्य तरीका है। बस उन्हें गिनो

    select count(*) as table_rows from table_name ; 

    सटीकता : क्वेरी चलाने के समय 100% सटीक गणना।
    दक्षता : बड़ी तालिकाओं के लिए अच्छा नहीं है। (MyISAM तालिकाओं के लिए शानदार रूप से तेज़ है, लेकिन कोई भी इन दिनों MyISAM का उपयोग नहीं कर रहा है क्योंकि इसमें InnoDB के इतने सारे नुकसान हैं। "शानदार रूप से तेज़" केवल पूरे MyISAM तालिका की पंक्तियों की गिनती करते समय ही लागू होता है - यदि क्वेरी में कोई WHEREशर्त है, तो यह अभी भी तालिका या एक सूचकांक को स्कैन करना है।)
    InnoDB तालिकाओं के लिए यह तालिका के आकार पर निर्भर करता है क्योंकि इंजन को सटीक गणना प्राप्त करने के लिए या तो पूरी तालिका या पूरे सूचकांक को स्कैन करना होता है। मेज जितनी बड़ी होगी, उतनी ही धीमी हो जाएगी।

  • बी) का उपयोग कर SQL_CALC_FOUND_ROWSऔर FOUND_ROWS()। पिछले तरीके के बजाय इस्तेमाल किया जा सकता है, अगर हम भी पंक्तियों की एक छोटी संख्या के साथ ही (बदलना LIMIT) चाहते हैं। मैंने इसे पेजिंग के लिए इस्तेमाल किया है (कुछ पंक्तियों को प्राप्त करने के लिए और एक ही समय में पता है कि कितने int int हैं और pgegs की संख्या की गणना करते हैं)।

    select sql_calc_found_rows * from table_name limit 0 ; 
    select found_rows() as table_rows ;

    सटीकता : पिछले जैसा ही।
    दक्षता : पिछले की तरह ही।

  • ग)information_schema लिंक किए गए प्रश्न के रूप में, तालिकाओं का उपयोग करना :

    select  table_rows
    from    information_schema.tables
    where   table_schema = 'database_name'
      and   table_name = 'table_name' ;

    सटीकता : केवल एक सन्निकटन। यदि तालिका लगातार आवेषण और हटाने का लक्ष्य है, तो परिणाम वास्तविक गणना से दूर हो सकता है। इसे ANALYZE TABLEअधिक बार चलाकर सुधारा जा सकता है ।
    दक्षता : बहुत अच्छा, यह तालिका को बिल्कुल भी नहीं छूता है।

  • डी) डेटाबेस में गणना को संग्रहीत करना (दूसरे, "काउंटर" तालिका में ) और उस मूल्य को हर बार अपडेट करें जब तालिका में एक सम्मिलित करें, हटाएं या छोटा करें (यह या तो ट्रिगर के साथ प्राप्त किया जा सकता है या सम्मिलित और संशोधित प्रक्रियाओं को संशोधित करके) ।
    यह निश्चित रूप से प्रत्येक डालने में एक अतिरिक्त भार डाल देगा और हटाएगा लेकिन एक सटीक गणना प्रदान करेगा।

    सटीकता : 100% सटीक गिनती।
    दक्षता : बहुत अच्छा है, किसी अन्य तालिका से केवल एक पंक्ति को पढ़ने की आवश्यकता है।
    यह डेटाबेस पर अतिरिक्त भार डालता है।

  • ई) आवेदन परत में गिनती ( कैशिंग ) - और 1 विधि (या पिछले विधियों का एक संयोजन) का उपयोग कर। उदाहरण: हर 10 मिनट में सटीक गणना क्वेरी चलाएँ। दो समय के बीच के बीच के समय में, कैश्ड मान का उपयोग करें।

    सटीकता : सन्निकटन लेकिन सामान्य परिस्थितियों में बहुत बुरा नहीं (जब तक कि हजारों पंक्तियों को जोड़ा या हटा न दिया जाए)।
    दक्षता : बहुत अच्छा, मूल्य हमेशा उपलब्ध है।


1

के लिए INNODBआप चाहते हैं information_schema.INNODB_SYS_TABLESTATS.NUM_ROWSके बजाय, सटीक तालिका पंक्ति संख्या डेटा के लिए information_schema.TABLES.TABLE_ROWS

मैंने यहां और अधिक विवरण पोस्ट किए: /programming/33383877/why-does-information-schema-tables-give-such-an-unstable-answer-for-number-of-ro/49184843#4918484343


1
गलत जानकारी ... "InnoDB के लिए आप सही तालिका पंक्ति के लिए information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS हैं:" मैनुअल स्पष्ट रूप से कहते हैं अनुमान पर NUM_ROWScolum
रेमंड Nijland
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.