बहुत बड़ी तालिका में पंक्तियों की सटीक संख्या गिनने का सबसे तेज़ तरीका?


234

मैं उस लेख पर आया हूं जो उस स्थिति SELECT COUNT(*) FROM TABLE_NAMEको धीमा करता है जब तालिका में बहुत सारी पंक्तियाँ और बहुत सारे कॉलम होते हैं।

मेरे पास एक तालिका है जिसमें अरबों पंक्तियाँ हो सकती हैं [इसमें लगभग 15 कॉलम हैं]। क्या तालिका की पंक्तियों की संख्या की सटीक गणना प्राप्त करने का एक बेहतर तरीका है ?

कृपया अपने उत्तर से पहले निम्नलिखित पर विचार करें:

  • मैं एक डेटाबेस विक्रेता स्वतंत्र समाधान की तलाश में हूं। यह ठीक है अगर यह MySQL , Oracle , MS SQL सर्वर को कवर करता है । लेकिन अगर वास्तव में कोई डेटाबेस विक्रेता स्वतंत्र समाधान नहीं है, तो मैं विभिन्न डेटाबेस विक्रेताओं के लिए अलग-अलग समाधानों के लिए समझौता करूंगा।

  • मैं ऐसा करने के लिए किसी अन्य बाहरी उपकरण का उपयोग नहीं कर सकता। मैं मुख्य रूप से SQL आधारित समाधान की तलाश में हूं।

  • मैं अपने डेटाबेस डिज़ाइन को और सामान्य नहीं कर सकता। यह पहले से ही 3NF में है और इसके आसपास बहुत सारे कोड पहले ही लिखे जा चुके हैं।


4
और बस जिज्ञासु की आवश्यकता क्यों है कि जब आप उनमें से अरबों हैं तो पंक्तियों की सटीक त्वरित राशि की जरूरत है ...
zerkms

2
क्या हम सभी आशा नहीं करेंगे कि यह विशेष निर्माण हमारे डेटाबेस विक्रेता द्वारा अनुकूलित किया गया है?
केविनडिमिम

5
@ सवरंगा, क्या आप इस डेटाबेस रखरखाव के उद्देश्य के बारे में थोड़ा और जान सकते हैं कि तालिका में पंक्तियों की सही संख्या ज्ञात होनी चाहिए ? मैं कल्पना नहीं कर सकता। और जैसा कि केविन कहते हैं, अगर COUNT (*) की तुलना में तेज़ तरीका था, तो DBMS विक्रेता को इसका उपयोग करने के लिए निश्चित रूप से COUNT (*) को फिर से लागू करना होगा ...
टोनी एंड्रयूज

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

2
आप एक रोलिंग गिनती रखने के लिए आवेषण का उपयोग कर सकते हैं और ट्रिगर हटा सकते हैं?
पापाराज़ो

जवाबों:


246

सरल उत्तर:

  • डेटाबेस विक्रेता स्वतंत्र समाधान = मानक का उपयोग करें = COUNT(*)
  • कर रहे हैं लगभग एसक्यूएल सर्वर समाधान लेकिन COUNT (*) का उपयोग नहीं करते क्षेत्र से बाहर =

टिप्पणियाँ:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) केवल मामले में

संपादित करें:

SQL सर्वर उदाहरण (1.4 बिलियन पंक्तियाँ, 12 कॉलम)

SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less

1 रन, 5:46 मिनट, गिनती = 1,401,659,700

--Note, sp_spaceused uses this DMV
SELECT
   Total_Rows= SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
    object_name(object_id) = 'MyBigtable' AND (index_id < 2)

2 रन, दोनों 1 सेकंड से कम, गिनती = 1,401,659,670

दूसरे में कम पंक्तियाँ हैं = गलत। लेखन के आधार पर समान या अधिक होंगे (हटाए गए घंटे यहां किए गए हैं)


9
नहीं, COUNT(*) = COUNT(key)। यह सिर्फ गलत है। यदि कोई NOT NULLबाधा नहीं है - तो वे समान नहीं हो सकते हैं (परिणामों के साथ-साथ निष्पादन योजना में)।
झटके

14
@zerkmsby: COUNT (कुंजी) के लिए मेरा मतलब COUNT (प्राथमिक) है जो कि अशक्त होना चाहिए। मैं स्पष्ट करूंगा
gbn

8
(NOLOCK) कुछ ऐसा नहीं है जो इसे उत्पादन पर चलाने की अनुमति देता है, और यह एक गलत गणना का कारण बन सकता है। जब आप उस संकेत का उपयोग करते हैं, तो सुनिश्चित करें कि यह ताले को रोकता है लेकिन एक उत्पादन बॉक्स पर दुष्प्रभाव यह है कि आप कुछ स्थितियों में दो बार पंक्तियों को गिन सकते हैं या अन्य स्थितियों में पंक्तियों को छोड़ सकते हैं। NOLOCK को एक ऐसी मेज पर उपयोग करना बेहतर होता है जिसे लिखा नहीं जा रहा है क्योंकि यह "गंदे रीड्स" की अनुमति देता है। लोगों को उस संकेत का उपयोग करने की सलाह न दें जब तक कि वे परिणामों को पूरी तरह से समझ न लें
दावोस

4
@mishrsud केवल सटीक क्वेरी ही SELECT COUNT (*) है, लेकिन यह धीमी है। आप या तो सटीक और धीमी गति से, या किसी न किसी और जल्दी हो सकता है। आप जो करते हैं वह इस बात पर निर्भर करेगा कि आपको जिस उद्देश्य के लिए गिनती की आवश्यकता है, उसके लिए क्या अधिक महत्वपूर्ण है। NO LOCK में शामिल हो सकते हैं या वास्तव में उन पंक्तियों को शामिल कर सकते हैं जो किसी भी कारण से मध्य-लेन-देन या चलते-फिरते पृष्ठ हैं।
दावोस

5
@ बहुत अच्छा समाधान, क्या आप बता सकते हैं कि इसका क्या उपयोग है index_id < 2?
प्रतिबद्ध

29

MySQL पर अब तक का सबसे तेज़ तरीका है:

SHOW TABLE STATUS;

यदि आप चाहते हैं तो आपको तुरंत अतिरिक्त गणना के साथ पंक्ति गणना (जो कुल है) के साथ अपने सभी टेबल मिलेंगे।


1
स्मार्ट तरीका..इसके बावजूद आप 1 क्वेरी में कई तालिकाओं की पंक्ति गणना प्राप्त कर सकते हैं।
देवल खंडेलवाल

क्या आपने @ जीबी की तरह ~ बिलियन प्रविष्टियों के साथ db टेबल पर चलाया और समय देखा?
KNU

डेटाबेस में सभी तालिकाओं के लिए कुल पंक्ति संख्या कौन सी है? और ये अनुमानित हैं - क्या होगा यदि आप सटीक पंक्ति गणना मान चाहते हैं?
क्रीवरप

2
उदाहरण के लिए, INNODB पर यह बिल्कुल भी काम नहीं करता है, भंडारण इंजन कुछ पंक्तियों को पढ़ता है और पंक्तियों की संख्या का अनुमान लगाने के लिए एक्सट्रपलेट करता है
Martijn Scheffer

10

मैं उन लेखों में आया हूं जो बताता है कि टेबल से बहुत सी पंक्तियाँ और बहुत सारे कॉलम होने पर TABLE_NAME से SELECT COUNT (*) धीमा हो जाएगा।

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

ध्यान दें कि आप आमतौर पर क्वेरी ऑप्टिमाइज़ेशन टूल्स, टेबल स्टैटिस्टिक्स आदि का उपयोग करके एक अच्छा अनुमान निकाल सकते हैं। उदाहरण के लिए, PostgreSQL के मामले में, आप explain count(*) from yourtableपंक्तियों की संख्या का यथोचित अच्छा अनुमान प्राप्त कर सकते हैं। जो मुझे आपके दूसरे सवाल पर लाता है।

मेरे पास एक तालिका है जिसमें अरबों पंक्तियाँ हो सकती हैं [इसमें लगभग 15 कॉलम हैं]। क्या तालिका की पंक्तियों की संख्या की सटीक गणना प्राप्त करने का एक बेहतर तरीका है?

गंभीरता से? :-) आपको वास्तव में अरबों पंक्तियों वाली तालिका से सटीक गणना का मतलब है ? क्या आपको पक्का विशवास है? :-)

यदि आप वास्तव में करते हैं, तो आप ट्रिगर्स का उपयोग करके कुल का एक ट्रेस रख सकते हैं, लेकिन यदि आप करते हैं तो माइंड कंसीलर और गतिरोध।


हां डेनिस, सटीक गणना आवश्यक है। :(
स्वरंगा सरमा

5
यह एक भाग्यशाली बात है कि Google प्रबंधक आपके बॉस की तुलना में अधिक उचित हैं ... चित्र यह अनुमान संख्या से चिपके रहने के बजाय आपके प्रत्येक प्रश्न के सटीक खोज परिणामों को वापस करने पर कितना धीमा होगा।
डेनिस डे बर्नार्डी

कम से कम आप मेरे साथ सहानुभूति रखते हैं। केवल ओरेकल समाधान के बारे में कैसे? यह मेरे मुद्दे को एक हद तक कम कर देगा। वर्तमान में ग्राहक Oracle का उपयोग कर रहा है; इसलिए अगर मैं केवल ओरेकल के लिए वर्कअराउंड के साथ आता हूं, तो वह [समय के लिए] करेगा। :)
स्वरंगा सरमा

6
"हां डेनिस, सटीक गणना आवश्यक है ।:(" - अच्छी तरह से मैं केवल अटकलें लगा सकता हूं। क्या डीबी रखरखाव प्रक्रिया से पता चलता है कि तालिका ए में 42,123,876 पंक्तियां हैं और फिर तालिका बी में 42,123,876 खाली पंक्तियां बनाएं और फिर तालिका के माध्यम से लूप करें। A और तालिका B में पंक्तियों को अपडेट करें ... या यह उससे अधिक क्रेज़ी है? ;-)
टोनी एंड्रयूज

1
लेनदेन 1 शुरू होने से पहले लेनदेन 2 शुरू नहीं हो सकता है। "काउंट टेबल" अपडेट के बिना, कई अपडेट लेनदेन समानांतर में चल सकते थे। "काउंट्स टेबल" के साथ, प्रत्येक लेन-देन को अपनी गिनती अपडेट करने के लिए "टिकट प्राप्त करना" होता है। इसलिए टिकट मशीन पर लेन-देन शुरू हो जाता है (यह तय करने वाला अनुसूचक कि काउंट टेबल पर ताला लगाने के लिए अगला कौन होगा)।
इरविन स्माउट

10

क्या तालिका की पंक्तियों की संख्या की सटीक गणना प्राप्त करने का एक बेहतर तरीका है?

बस अपने सवाल का जवाब देने के लिए, नहीं

यदि आपको ऐसा करने का स्वतंत्र तरीके से DBMS की आवश्यकता है, तो सबसे तेज़ तरीका हमेशा रहेगा:

SELECT COUNT(*) FROM TableName

कुछ डीबीएमएस विक्रेताओं के पास तेज तरीके हो सकते हैं जो केवल उनके सिस्टम के लिए काम करेंगे। इनमें से कुछ विकल्प पहले से ही अन्य उत्तरों में पोस्ट किए गए हैं।

COUNT(*) वैसे भी DBMS (कम से कम किसी भी PROD योग्य डीबी) द्वारा अनुकूलित किया जाना चाहिए, ताकि उनके अनुकूलन को बायपास करने की कोशिश न करें।

एक साइड नोट पर:
मुझे यकीन है कि आपके कई अन्य प्रश्नों को भी आपके टेबल के आकार के कारण समाप्त होने में लंबा समय लगता है। किसी भी प्रदर्शन संबंधी चिंताओं को संभवतः आपके स्कीमा डिज़ाइन के बारे में सोचकर ध्यान में रखा जाना चाहिए। मुझे लगता है कि आपने कहा था कि यह बदलने का विकल्प नहीं है, लेकिन यह पता चल सकता है कि 10+ मिनट के प्रश्न भी विकल्प नहीं हैं। तीसरा NF हमेशा सबसे अच्छा तरीका नहीं है जब आपको गति की आवश्यकता होती है, और कभी-कभी डेटा को कई तालिकाओं में विभाजित किया जा सकता है यदि रिकॉर्ड को एक साथ संग्रहीत नहीं करना है। कुछ चीजें सोचने के लिये...


10

मुझे एक और StackOverflow प्रश्न / उत्तर से यह स्क्रिप्ट मिली:

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

मेरी तालिका में 500 मिलियन रिकॉर्ड और उपरोक्त रिटर्न 1 मी से कम है। इस दौरान,

SELECT COUNT(id) FROM MyTable

पूरे 39 मिनट, 52 सेकंड लगते हैं!

वे ठीक उसी संख्या में पंक्तियों की उपज देते हैं (मेरे मामले में, बिल्कुल 519326012)।

मुझे नहीं पता कि ऐसा हमेशा होता।


क्या आप इस क्वेरी के साथ पंक्तियाँ गिनने के लिए कोई पैरामीटर जोड़ सकते हैं? उदाहरण: TABLENAME से COUNT (1) का चयन करें जहां कॉलमफ़िल्ड = '1' आपकी क्वेरी के साथ है?
VnDevil

वह गिनती है - पंक्तियों की संख्या (रिकॉर्ड) इस मामले में "गिनती" है। "500 मिलियन रिकॉर्ड" एक अनुमानित संख्या थी, और "519326012" पंक्तियों, या गिनती की सटीक संख्या थी। पंक्तियाँ = अभिलेख = गिनती।
जेकज

9

आप इसे sp_spaceused (Transact-SQL) आज़मा सकते हैं

वर्तमान डेटाबेस में पंक्तियों की संख्या, डिस्क स्थान आरक्षित, और तालिका द्वारा प्रयुक्त डिस्क स्थान, अनुक्रमित दृश्य, या सेवा ब्रोकर कतार प्रदर्शित करता है, या पूरे डेटाबेस द्वारा आरक्षित और उपयोग किए गए डिस्क स्थान को प्रदर्शित करता है।


Sp_spaceused मुझे एक अनुमानित संख्या नहीं देंगे?
स्वरंगा सरमा

1
FYI करें: यह आंतरिक रूप से sysinos_db_partition_stats का उपयोग करता है
gbn

6

यदि SQL Server संस्करण 2005/2008 है, तो आप तालिका में पंक्ति गणना की गणना करने के लिए DMV का उपयोग कर सकते हैं:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name, 
 ddps.row_count 
FROM sys.indexes AS i 
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0 
ORDER BY o.NAME 

SQL सर्वर 2000 डेटाबेस इंजन के लिए, sysindexes काम करेगा, लेकिन इसे SQL सर्वर के भविष्य के संस्करणों में उपयोग करने से बचने की दृढ़ता से सलाह दी जाती है क्योंकि निकट भविष्य में इसे हटाया जा सकता है।

से लिया गया सैंपल कोड: टेबल रो को कैसे प्राप्त करें जल्दी और बिना किसी परेशानी के


यह वह जगह है लगभग नहीं सटीक : देखना मेरा उत्तर कृपया
GBN

क्या आप एक उदाहरण जानते हैं कि यह कहाँ सटीक नहीं है? AFAIK, यह अद्यतन आँकड़ों पर निर्भर नहीं करता है।
अलीरज़ा मद्दाह


5

मैं कहीं नहीं के रूप में विशेषज्ञ के रूप में दूसरों के रूप में जो उत्तर दिया है, लेकिन मैं एक प्रक्रिया के साथ एक समस्या थी मैं एक तालिका से यादृच्छिक पंक्ति का चयन करने के लिए उपयोग कर रहा था (अत्यधिक प्रासंगिक नहीं) लेकिन मुझे अपनी संदर्भ तालिका में पंक्तियों की संख्या जानने की आवश्यकता थी यादृच्छिक सूचकांक की गणना करने के लिए। पारंपरिक गणना (*) या काउंट (1) कार्य का उपयोग करना लेकिन मुझे कभी-कभी अपनी क्वेरी को चलाने के लिए 2 सेकंड तक का समय मिल रहा था। इसलिए इसके बजाय ('tbl_HighOrder' नाम की मेरी तालिका के लिए) मैं उपयोग कर रहा हूं:

Declare @max int

Select @max = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'tbl_HighOrder'

यह महान काम करता है और प्रबंधन स्टूडियो में क्वेरी समय शून्य है।


1
एफडब्ल्यूआईडब्ल्यू, आपको उस डेटाबेस डेटाबेस विक्रेता का उल्लेख करना चाहिए जिसका आप उपयोग कर रहे हैं; मुझे लगता है कि विक्रेता के आधार पर बयान थोड़ा अलग होगा।
टूलमेकरसिटेव

5

खैर, 5 साल की देरी और अनिश्चित अगर यह मदद करता है:

मैं नहीं की गिनती करने की कोशिश कर रहा था। MS SQL सर्वर प्रबंधन स्टूडियो का उपयोग करते हुए SQL सर्वर तालिका में पंक्तियों और कुछ अतिप्रवाह त्रुटि में भाग गया, तो मैंने नीचे का उपयोग किया:

चयन COUNT_BIG [dbname] से (1) [dbo] [FactSampleValue]।।

परिणाम :

24296650578 पंक्तियाँ


5

मुझे यह अच्छा लेख मिला SQL Server-HOW-TO: जल्दी से तालिका के लिए सटीक पंक्ति गणना प्राप्त करनाmartijnh1 जिसमें से प्रत्येक परिदृश्य के लिए एक अच्छा पुनरावृत्ति देता है।

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

इस बीच, यहाँ लेख से विवरण हैं:

विधि 1:

प्रश्न:

SELECT COUNT(*) FROM Transactions 

टिप्पणियाँ:

एक पूर्ण तालिका स्कैन करता है। बड़े तालिकाओं पर धीमा।

विधि 2:

प्रश्न:

SELECT CONVERT(bigint, rows) 
FROM sysindexes 
WHERE id = OBJECT_ID('Transactions') 
AND indid < 2 

टिप्पणियाँ:

पंक्ति गणना को पुनः प्राप्त करने का तेज़ तरीका। आंकड़ों पर निर्भर करता है और गलत है।

COUNT_ROWS के साथ DBCC UPDATEUSAGE (डेटाबेस) चलाएं, जो बड़ी तालिकाओं के लिए महत्वपूर्ण समय ले सकता है।

विधि 3:

प्रश्न:

SELECT CAST(p.rows AS float) 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
AND p.index_id=idx.index_id 
WHERE ((tbl.name=N'Transactions' 
AND SCHEMA_NAME(tbl.schema_id)='dbo')) 

टिप्पणियाँ:

जिस तरह से SQL प्रबंधन स्टूडियो पंक्तियों को गिनता है (तालिका गुणों, भंडारण, पंक्ति गणना को देखें)। बहुत तेज़, लेकिन फिर भी पंक्तियों की अनुमानित संख्या।

विधि 4:

प्रश्न:

SELECT SUM (row_count) 
FROM sys.dm_db_partition_stats 
WHERE object_id=OBJECT_ID('Transactions')    
AND (index_id=0 or index_id=1); 

टिप्पणियाँ:

त्वरित (हालांकि विधि 2 जितना तेज़ नहीं) ऑपरेशन और उतना ही महत्वपूर्ण, विश्वसनीय।


धन्यवाद! वास्तव में उपयोगी टिप। मुझे सिस्टम टेबल देखने की अनुमति नहीं है इसलिए विधि 4 मैं नहीं हूं। हालाँकि विधि 3 पर्याप्त अच्छी है।
निकोलस हम्फ्री

3

मुझे नहीं लगता कि एक सामान्य हमेशा-सबसे तेज़ समाधान है: कुछ आरडीबीएमएस / संस्करणों के लिए एक विशिष्ट अनुकूलन है SELECT COUNT(*)जो तेज़ विकल्पों का उपयोग करते हैं जबकि अन्य बस टेबल-स्कैन करते हैं। आपको दूसरे सेट के लिए प्रलेखन / समर्थन साइटों पर जाने की आवश्यकता होगी, जिसे लिखने के लिए संभवतः कुछ और विशिष्ट क्वेरी की आवश्यकता होगी, आमतौर पर एक जो किसी तरह से एक सूचकांक को हिट करता है।

संपादित करें:

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


मुझे बहुत उम्मीद है कि किसी भी सभ्य DBMS के लिए एक सूचकांक का उपयोग करेगा SELECT COUNT(*)। यहां तक ​​कि MySQL जाहिरा तौर पर यह करता है ...।
20'11

हटाने को गंभीरता से नहीं लेते - गंभीरता से ?? ; पी
टूलमेकरसेव

3

मुझे इस प्रश्न की देर है, लेकिन यहाँ आप MySQL के साथ क्या कर सकते हैं (जैसा कि मैं MySQL का उपयोग करता हूँ)। मैं अपनी टिप्पणियों को यहां साझा कर रहा हूं:

1) SELECT COUNT(*) AS TOTAL_ROWS FROM <TABLE_NAME>

परिणाम
पंक्ति गणना: 508534
कंसोल आउटपुट: प्रभावित पंक्तियाँ: 0 मिली पंक्तियाँ: 1 चेतावनियाँ: 0 1 क्वेरी के लिए अवधि: 0.125 सेकंड।
बड़ी संख्या में पंक्तियों वाली तालिका के लिए कुछ समय लगता है, लेकिन पंक्ति गणना बहुत सटीक है।

2) SHOW TABLE STATUS or SHOW TABLE STATUS WHERE NAME="<TABLE_NAME>"

परिणाम
पंक्ति गणना: 511235
कंसोल आउटपुट: प्रभावित पंक्तियाँ: 0 मिली पंक्तियाँ: 1 चेतावनियाँ: 0 1 क्वेरी के लिए अवधि: 0.250 सेकंड सारांश: पंक्ति गणना सटीक नहीं है।

3) SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();

परिणाम
पंक्ति गणना: 507806
कंसोल आउटपुट: प्रभावित पंक्तियाँ: 0 मिली पंक्तियाँ: 48 चेतावनियाँ: 0 1 क्वेरी के लिए अवधि: 1.701 सेकंड।
पंक्ति गणना सटीक नहीं है।

मैं एक MySQL या डेटाबेस विशेषज्ञ नहीं हूं, लेकिन मैंने पाया है कि बहुत बड़ी तालिकाओं के लिए, आप विकल्प 2 या 3 का उपयोग कर सकते हैं और कितनी पंक्तियों में मौजूद हैं, इसका 'उचित विचार' प्राप्त कर सकते हैं।

मुझे UI पर कुछ आँकड़े प्रदर्शित करने के लिए इन पंक्ति गणनाओं को प्राप्त करने की आवश्यकता थी। उपरोक्त प्रश्नों के साथ, मुझे पता था कि कुल पंक्तियाँ 500,000 से अधिक थीं, इसलिए मैं "पंक्तियों की सही संख्या दिखाए बिना" 500,000 से अधिक पंक्तियों जैसे आँकड़े दिखाने के साथ आया था।

शायद मैंने वास्तव में ओपी के सवाल का जवाब नहीं दिया है, लेकिन मैं उस स्थिति में साझा कर रहा हूं जो मैंने उस स्थिति में किया था जहां ऐसे आंकड़ों की जरूरत थी। मेरे मामले में, अनुमानित पंक्तियों को दिखाना स्वीकार्य था और इसलिए ऊपर वाले ने मेरे लिए काम किया।


2

डीबीएमएस-अज्ञेय समाधान बिल्कुल नहीं, लेकिन कम से कम आपके ग्राहक कोड में अंतर नहीं दिखेगा ...

केवल एक पंक्ति और एक पूर्णांक फ़ील्ड N 1 के साथ एक और तालिका T बनाएँ , और INSERT TRIGGER बनाएं जो बस निष्पादित करता है:

UPDATE T SET N = N + 1

निष्पादित करने वाला एक DELETE TRIGGER भी बनाएं:

UPDATE T SET N = N - 1

अपने नमक के लायक एक DBMS 2 से ऊपर के संचालन की परमाणुता की गारंटी देगा , और N में हर समय पंक्तियों की सटीक गणना शामिल होगी, जो कि बस द्वारा प्राप्त करने के लिए अति-त्वरित है:

SELECT N FROM T

ट्रिगर्स DBMS- विशिष्ट होते हैं, T से चयन नहीं होता है और आपके क्लाइंट कोड को प्रत्येक समर्थित DBMS के लिए बदलने की आवश्यकता नहीं होगी।

हालाँकि, यह कुछ स्केलेबिलिटी समस्याएँ हो सकती हैं यदि तालिका INSERT या DELETE- गहन है, खासकर यदि आप INSERT / DELETE के तुरंत बाद कमिट नहीं करते हैं।


1 ये नाम सिर्फ प्लेसहोल्डर हैं - उत्पादन में कुछ अधिक सार्थक उपयोग करते हैं।

2 I N को पढ़ने और लिखने के बीच के समवर्ती लेनदेन द्वारा नहीं बदला जा सकता है, जब तक कि पढ़ना और लिखना दोनों एक ही SQL स्टेटमेंट में नहीं किए जाते हैं।


2

एक शाब्दिक रूप से पागल जवाब, लेकिन अगर आपके पास किसी तरह की प्रतिकृति प्रणाली स्थापित है (एक बिलियन पंक्तियों वाली प्रणाली के लिए, मुझे आशा है कि आप करते हैं), तो आप किसी न किसी अनुमानक (जैसे MAX(pk)) का उपयोग कर सकते हैं , उस मूल्य को दासों की संख्या से विभाजित कर सकते हैं आपके पास समानांतर में कई प्रश्न हैं।

अधिकांश भाग के लिए, आप सबसे अच्छी कुंजी (या प्राथमिक कुंजी जो मुझे लगता है) के आधार पर दासों के प्रश्नों का विभाजन करेंगे, इस तरह से (हम अपनी पंक्तियों / दासों के रूप में 250000000 का उपयोग करने जा रहे हैं):

-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000

लेकिन आपको SQL की ही जरूरत है। क्या हलचल है। ठीक है, तो हम कहते हैं कि तुम एक sadomasochist हो। मास्टर (या निकटतम दास) पर आपको इसके लिए एक तालिका बनाने की आवश्यकता होगी:

CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)

इसलिए केवल आपके गुलामों में चयन होने के बजाय, आपको इसके लिए एक इंसर्ट करना होगा, जैसे:

INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)

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

-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)

आपको अंत में एक गुलाम होना चाहिए जो पहले ग्राफ के सापेक्ष प्रतिकृति ग्राफ के आधार पर पथ में अंतिम रूप से मौजूद है। उस दास के पास अब अन्य सभी काउंटर मूल्य होने चाहिए, और उसके अपने मूल्य होने चाहिए। लेकिन जब तक आप समाप्त कर लेते हैं, तब संभवतः पंक्तियाँ जुड़ जाती हैं, इसलिए आपको अपने काउंटर_टेबल में रिकॉर्ड किए गए अधिकतम pk और वर्तमान अधिकतम pk के लिए एक और क्षतिपूर्ति करनी होगी।

उस बिंदु पर, आपको कुल पंक्तियों का पता लगाने के लिए एक समग्र कार्य करना होगा, लेकिन यह आसान है क्योंकि आप इसे "आपके पास मौजूद दासों की संख्या और पंक्तियों को बदलने" पर सबसे अधिक चल रहे हैं।

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

SELECT SUM(cnt) FROM (
    SELECT * FROM counter_table_slave_1
      UNION
    SELECT * FROM counter_table_slave_2
      UNION
    ...
  )

या आप जानते हैं, थोड़ा कम पागल हो और अपने डेटा को एक वितरित प्रसंस्करण प्रणाली में माइग्रेट करें, या शायद एक डेटा वेयरहाउसिंग समाधान का उपयोग करें (जो आपको भविष्य में भी भयानक डेटा क्रंचिंग देगा)।

ध्यान दें, यह इस बात पर निर्भर करता है कि आपकी प्रतिकृति कितनी अच्छी है। चूंकि प्राथमिक अड़चन सबसे अधिक संभावना होगी, अगर आपके पास भारी पड़ोसी शोर के साथ खराब भंडारण या खराब रूप से अलग किए गए डेटा स्टोर हैं, तो यह संभवतः आपको एक ही इंतजार करने की तुलना में धीमी गति से चलाएगा।SELECT COUNT(*) ...

लेकिन अगर आपके पास अच्छी प्रतिकृति है, तो आपका गति लाभ सीधे संख्या या दास से संबंधित होना चाहिए। वास्तव में, यदि काउंटिंग क्वेरी को अकेले चलाने में 10 मिनट लगते हैं, और आपके पास 8 दास हैं, तो आप अपना समय एक दो मिनट से भी कम समय में काट लेंगे। हो सकता है कि इस समाधान के विवरण को जानने के लिए एक घंटे का समय हो।

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

वास्तव में, यह असंभव लगता है, क्योंकि आप मूल रूप से एक एसक्यूएल-केवल समाधान के साथ फंस गए हैं, और मुझे नहीं लगता है कि आपको कई दासों को तुरंत एक शार्प और लॉक किए गए क्वेरी को चलाने के लिए एक तंत्र प्रदान किया गया है। हो सकता है कि यदि आपके पास प्रतिकृति लॉग फ़ाइल का नियंत्रण था ... जिसका अर्थ है कि आप सचमुच इस उद्देश्य के लिए गुलाम बनेंगे, जो कि वैसे भी एक मशीन पर गिनती क्वेरी को चलाने की तुलना में कोई संदेह नहीं है।

तो वहाँ मेरे दो 2013 पैसा है।


2

यदि डालने ट्रिगर भी उपयोग करने के लिए महंगा है, लेकिन एक नष्ट ट्रिगर समर्थ बनाया जा सकता है, और वहाँ एक स्वत: वेतन वृद्धि हैid , तो पूरे तालिका एक बार गिनती, और के रूप में गिनती याद के बाद last-countऔर last-counted-id,

फिर हर दिन बस id> के लिए गिनती करने की जरूरत है last-counted-id, कि जोड़ने के लिए last-countऔर नए स्टोर last-counted-id

हटाए गए ट्रिगर अंतिम-गणना में कमी आएगी, यदि हटाए गए रिकॉर्ड की आईडी <= अंतिम-गिनती-आईडी।


क्षमा करें, एसक्यूएल का उपयोग करने के लिए समय नहीं है (मेरा एसक्यूएल जंग खा गया है)। अगर कोई एसक्यूएल जोड़ने के लिए मेरे जवाब को संपादित करना चाहता है, तो यह बहुत अच्छा होगा!
टूलमेकर 14

1

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

SELECT TOP(1) <primarykeyfield> FROM <table> ORDER BY <primarykeyfield> DESC;

मैं एमएस SQL ​​टेबल के साथ काम करता हूं जिसमें अरबों पंक्तियां होती हैं जिनके लिए रिकॉर्ड काउंट सहित डेटा के लिए सब-सेकंड रिस्पॉन्स टाइम की आवश्यकता होती है। एक समान सेलेक्ट COUNT (*) की तुलना में प्रक्रिया में मिनट लगेंगे।


1
पूरी तरह से सच नहीं है - क्या होगा अगर एक INSERTलेनदेन वापस लुढ़का हुआ है? वह प्राथमिक कुंजी मान अनुपस्थित होगा, इसलिए वास्तविक रिकॉर्ड संख्या अधिकतम मान से कम होगी।
सर क्रिस्पलॉट

क्रमानुसार अंतराल हो सकता है। आमतौर पर रोलबैक का एक परिणाम।
ओसा ई

वास्तव में, इस उत्तर का एक संशोधन है जो काफी तेजी से हो सकता है count(*), अगर एक डेटाबेस विक्रेता ने पर्याप्त रूप से अनुकूलित नहीं किया है count(*): प्रत्येक दिन अंतिम ऑटो-इंडेक्स और उसके अनुरूप गणना का ट्रैक रखें, फिर पिछले रिकॉर्ड की एक गिनती के लिए पूछें। यह भी deleteहटा सकता है कि यदि पिछले रिकॉर्ड को हटाने वाले डिलीट पर कोई ट्रिगर जोड़ें , यदि डिलीट किया गया रिकॉर्ड आईडी <= जो अंतिम ऑटो-इंडेक्स है।
टूलमेकरसेव

1

Sql सर्वर के लिए यह प्रयास करें

SELECT T.name, 
       I.rows AS [ROWCOUNT] 
FROM   sys.tables AS T 
       INNER JOIN sys.sysindexes AS I 
               ON T.object_id = I.id AND I.indid < 2 
WHERE T.name = 'Your_Table_Name'
ORDER  BY I.rows DESC 

0

sysindexes से पंक्तियों का चयन करें जहाँ id = Object_ID ('TableName') और indid <2


0

कुछ कॉलम पर एक इंडेक्स डालें। तालिका के पूर्ण स्कैन के बजाय, आशावादी को सूचकांक ब्लॉकों का पूर्ण स्कैन करने की अनुमति देनी चाहिए। इससे आपकी IO लागत में कमी आएगी। पहले और बाद में निष्पादन योजना को देखें। फिर दोनों तरीकों से दीवार घड़ी का समय मापें।


यदि किसी तालिका में किसी भी स्तंभ पर एक सूचकांक के बिना अरबों पंक्तियाँ हैं, तो व्यापक प्रदर्शन के मुद्दे होंगे, मूल प्रश्न में व्यक्त की आवश्यकता से परे .. लेकिन अच्छा है कि आप इसका उल्लेख करें (कुछ भी नहीं
मानें

0

यदि आप ओरेकल का उपयोग कर रहे हैं, तो इस बारे में कैसे (तालिका के आँकड़े अपडेट किए गए हैं):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

last_analyzed वह समय दिखाएगा जब आँकड़े अंतिम रूप से एकत्रित किए गए थे।



-1

SQL सर्वर 2016 में, मैं बस तालिका गुणों की जांच कर सकता हूं और फिर 'स्टोरेज' टैब का चयन कर सकता हूं - इससे मुझे पंक्ति गणना, तालिका द्वारा उपयोग किया जाने वाला डिस्क स्थान, उपयोग किए गए सूचकांक स्थान आदि मिलते हैं।


वह एक की तलाश में था database vendor independent solution। इसके अलावा इसमें GUI की आवश्यकता होती है और इसे स्वचालित नहीं किया जा सकता है। इसके अलावा यह COUNT (*) के रूप में तेज़ नहीं है
फ्राइडर

-3

शायद थोड़ी देर हो जाए, लेकिन इससे दूसरों को MSSQL की मदद मिल सकती है

, RecordCount के साथ (SELOW ROW_NUMBER () OVER (ORDER BY COLUMN_NAME) के रूप में [RowNumber] से TABLE_NAME) का चयन करें MAX (RowNumber) से रिकॉर्ड करें


यह COUNT () से अधिक महत्वपूर्ण है, जब तक हम बहुत भाग्यशाली नहीं होते हैं और आशावादी इसे COUNT () में अनुकूलित करने का प्रबंधन करता है - इसे यादृच्छिक कॉलम पर SORT करने के लिए क्यों कहें?!?
dsz
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.