MySQL में तेजी से, DISTINCT या GROUP BY का चयन करें?


273

अगर मेरे पास कोई टेबल है

CREATE TABLE users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  profession varchar(255) NOT NULL,
  employer varchar(255) NOT NULL,
  PRIMARY KEY  (id)
)

और मैं professionक्षेत्र के सभी अद्वितीय मूल्यों को प्राप्त करना चाहता हूं , जो तेज (या अनुशंसित) होंगे:

SELECT DISTINCT u.profession FROM users u

या

SELECT u.profession FROM users u GROUP BY u.profession

?


2
आप अपने आप को परीक्षण के रूप में जल्दी के रूप में सवाल पूछ सकते हैं। चिड़चिड़ापन, एक परिदृश्य का निर्माण करना लगभग असंभव है जिसमें DISTINCT आउटपरफॉर्म ग्रुप BY - जो कष्टप्रद है क्योंकि स्पष्ट रूप से यह ग्रुप BY का उद्देश्य नहीं है। हालाँकि, GROUP BY भ्रामक परिणाम दे सकता है, जो मुझे लगता है कि इसे टालने के लिए पर्याप्त है।
स्ट्रॉबेरी

एक अलग उत्तर के साथ एक और डुप्लिकेट है। देखें MySql - डिस्ट्रिक्ट बनाम ग्रुप बाय <<< का कहना है कि ग्रुप बाय बेहतर है
कोलूनर

कृपया देखें यहाँ अगर आप अपने क्वेरी चलाकर अलग और ग्रुप के बीच समय अंतर का आकलन करना चाहते।
कोल्लुनार '

जवाबों:


258

वे अनिवार्य रूप से एक दूसरे के बराबर हैं (वास्तव में यह है कि कुछ डेटाबेस DISTINCTहुड के तहत कैसे लागू होते हैं )।

यदि उनमें से एक तेज है, तो यह होने जा रहा है DISTINCT। ऐसा इसलिए है, हालांकि दोनों समान हैं, एक क्वेरी ऑप्टिमाइज़र को इस तथ्य को पकड़ना होगा कि आपका GROUP BYकोई समूह सदस्यों का लाभ नहीं उठा रहा है, बस उनकी चाबियाँ। DISTINCTयह स्पष्ट करता है, इसलिए आप थोड़ा डम्बर ऑप्टिमाइज़र के साथ भाग सकते हैं।

जब संदेह में, परीक्षण!


76
DISTINCT तेजी से केवल तभी होगा जब आपके पास कोई इंडेक्स नहीं होगा (क्योंकि यह सॉर्ट नहीं करता है)। जब आपके पास एक सूचकांक होता है और इसका उपयोग किया जाता है, तो वे समानार्थक होते हैं।
क्वासोनि

10
की परिभाषा DISTINCTऔर इसमें GROUP BYअलग - अलग DISTINCTआउटपुट को सॉर्ट करना नहीं है, और GROUP BYडिफ़ॉल्ट रूप से होता है। हालांकि, MySQL में भी एक DISTINCT+ ORDER BYहो सकता है अभी भी तेजी से एक से हो GROUP BYअनुकूलक के लिए अतिरिक्त संकेत के कारण के रूप में SquareCog से समझाया।
15 जून को 15

1
DISTINCT बड़ी राशि डेटा के साथ बहुत तेज़ है।
पंकज वंजारी

7
मैंने इसका परीक्षण किया, और पाया कि एक अनुक्रमित स्तंभ पर, mysql, समूह द्वारा एक काफी जटिल प्रश्न के साथ अलग से लगभग 6x धीमा था। बस इसे एक डाटापॉइंट के रूप में जोड़ना है। लगभग 100k पंक्तियों। इसलिए इसका परीक्षण करें और अपने लिए देखें।
छिपकली


100

यदि आपके पास एक सूचकांक है profession, तो ये दोनों समानार्थक हैं।

यदि आप नहीं करते हैं, तो उपयोग करें DISTINCT

GROUP BYमें MySQLप्रकार का परिणाम है। आप भी कर सकते हैं:

SELECT u.profession FROM users u GROUP BY u.profession DESC

और अपने व्यवसायों को DESCक्रम में क्रमबद्ध करें।

DISTINCTएक अस्थायी तालिका बनाता है और डुप्लिकेट के भंडारण के लिए इसका उपयोग करता है। GROUP BYवही करता है, लेकिन बाद में अलग-अलग परिणामों को हल करता है।

इसलिए

SELECT DISTINCT u.profession FROM users u

यदि आपके पास कोई अनुक्रमणिका नहीं है, तो यह तेज़ है profession


6
आप जोड़ सकते हैं ORDER BY NULLकरने के लिए GROUP BYतरह से बचने के लिए।
एरियल

शून्य से समूहन के साथ फिर भी धीमा
थान ट्रुंग

@ थनट्रंग: क्या की तुलना में धीमी है?
क्वासोई

@Quassnoi समूह से अलग भले ही अलग तरह से धीमी हो
थान ट्रुंग

नोट: ग्रुप बाय पर ऑर्डर क्वालीफायर MySQL 8 में पदावनत किए गए थे।
मैथ्यू लेनज

18

ऊपर दिए गए सभी उत्तर सही हैं, एक कॉलम पर एक समूह बनाम ग्रुप BY पर DISTINCT के मामले के लिए। हर डीबी इंजन का अपना कार्यान्वयन और अनुकूलन होता है, और यदि आप बहुत कम अंतर (ज्यादातर मामलों में) की परवाह करते हैं, तो आपको विशिष्ट सर्वर और विशिष्ट संस्करण के खिलाफ परीक्षण करना होगा! जैसा कि कार्यान्वयन बदल सकते हैं ...

लेकिन, यदि आप क्वेरी में एक से अधिक कॉलम चुनते हैं, तो DISTINCT अनिवार्य रूप से अलग है! क्योंकि इस मामले में यह सभी पंक्तियों के सभी स्तंभों की तुलना करेगा, बजाय केवल एक कॉलम के।

तो अगर आपके पास कुछ ऐसा है:

// This will NOT return unique by [id], but unique by (id,name)
SELECT DISTINCT id, name FROM some_query_with_joins

// This will select unique by [id].
SELECT id, name FROM some_query_with_joins GROUP BY id

यह सोचना एक सामान्य गलती है कि DISTINCT कीवर्ड आपके द्वारा निर्दिष्ट पहले कॉलम द्वारा पंक्तियों को अलग करता है, लेकिन DISTINCT इस तरह से एक सामान्य कीवर्ड है।

इसलिए आपको उन लोगों से सावधान रहना होगा जो ऊपर दिए गए उत्तरों को सभी मामलों के लिए सही नहीं मान सकते हैं ... आप भ्रमित हो सकते हैं और गलत परिणाम प्राप्त कर सकते हैं, जबकि आप जो चाहते थे वह सभी को अनुकूलित करना था!


3
हालांकि इस सवाल है MySQL के बारे में यह ध्यान दिया जाना चाहिए कि दूसरी क्वेरी काम करेंगे केवल MySQL में। लगभग हर दूसरे DBMS दूसरे कथन को अस्वीकार कर देगा क्योंकि यह GROUP BY ऑपरेटर का अमान्य उपयोग है।
a_horse_with_no_name

खैर, "लगभग" एक समस्याग्रस्त परिभाषा है :-) यदि आप एक विशिष्ट डीबीएमएस है जिसे आपने यह देखने के लिए परीक्षण किया है कि यह कथन के लिए एक त्रुटि उत्पन्न करता है, तो यह अधिक उपयोगी होगा ।
daniel.gindi

3
शुरुआत के लिए Postgres, Oracle, Firebird, DB2, SQL Server। MySQL: sqlfiddle.com/#/2/6897c/1 Postgres: sqlfiddle.com/#/12/6897c/1 Oracle: sqlfiddle.com/# -12 / 6897c/1 SQL Server: sqlfield.com/## -6! 6897c / 1
a_horse_with_no_name

17

यदि आप कर सकते हैं सबसे सरल और कम से कम के लिए जाओ - DISTINCT अधिक लग रहा है कि आप केवल इसलिए देख रहे हैं क्योंकि यह आपको सही उत्तर देगा जो आपको केवल और केवल आवश्यकता है!


7

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

SELECT DISTINCT u.profession FROM users u

के बराबर है

SELECT u.profession FROM users u GROUP BY u.profession order by null

के बराबर हैSELECT profession FROM users GROUP BY profession

6

पोस्टग्रेज में कुछ अवसरों पर समूह की तुलना में अच्छी तरह से अलग हो सकता है (अन्य dbs के बारे में पता नहीं)।

परीक्षण किया गया उदाहरण:

postgres=# select count(*) from (select distinct i from g) a;

count 

10001
(1 row)

Time: 1563,109 ms

postgres=# select count(*) from (select i from g group by i) a;

count
10001
(1 row)

Time: 594,481 ms

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

तो सावधान रहें ... :)


5

ऐसा लगता है कि प्रश्न बिल्कुल समान नहीं हैं। कम से कम MySQL के लिए।

की तुलना करें:

  1. नॉर्थविंड.प्रोडक्ट से अलग प्रोडक्टनेम चुनें
  2. उत्पाद नाम से नॉर्थविंड.प्रोडक्ट समूह से चुनिंदा उत्पादनाम का वर्णन करें

दूसरी क्वेरी अतिरिक्त रूप से "फाइल का उपयोग कर" अतिरिक्त में देती है।


1
उन्हें वही मिलता है जो उन्हें मिलता है, न कि वे इसे पाने के संदर्भ में। एक आदर्श ऑप्टिमाइज़र उन्हें उसी तरह निष्पादित करेगा, लेकिन MySQL ऑप्टिमाइज़र आदर्श नहीं है। आपके सबूतों के आधार पर, ऐसा लगता है कि DISTINCT तेजी से जाएगा - O (n) बनाम O (n * log n)।
स्क्वायरकॉग

तो, "फाइलशॉर्ट का उपयोग करना" अनिवार्य रूप से बुरी बात है?
वावा

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

1
जोड़े ORDER BY NULLको GROUP BYसंस्करण और वे एक ही हो जाएगा।
एरियल

3

में MySQL , " Group By" एक अतिरिक्त कदम का उपयोग करता है: filesort। मुझे एहसास हुआ कि इससे DISTINCTभी तेज है GROUP BY, और यह एक आश्चर्य था।


3

भारी परीक्षण के बाद हम इस निष्कर्ष पर पहुंचे कि ग्रुप बाय तेज है

से चयन sql_no_cache opnamegroep_intern telwerken कहां opnemergroepIN (7,8,9,10,11,12,13) opnamegroep_intern द्वारा समूह

635 टोटल 0.0944 सेकेंड में वेर्गेव वैन रिकॉर्ड 0 - 29 (635 टोटल, क्वेरी ड्यूरेड 0.03444)

चयन करें sql_no_cache अलग (opnamegroep_intern) telwerken जहां से opnemergroep(7,8,9,10,11,12,13)

635 टोटल 0.2117 सेकंड (लगभग 100% धीमा) वेर्गवे वैन रिकॉर्ड 0 - 29 (635 टोटल, क्वेरी ड्यूरेड 0.3468 सेकंड)


2

(एक कार्यात्मक नोट के अधिक)

ऐसे मामले हैं जब आपको ग्रुप बीई का उपयोग करना पड़ता है, उदाहरण के लिए यदि आप प्रति नियोक्ता कर्मचारियों की संख्या प्राप्त करना चाहते हैं:

SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer

ऐसे परिदृश्य में DISTINCT u.employerसही काम नहीं करता है। शायद एक रास्ता है, लेकिन मुझे अभी यह पता नहीं है। (यदि कोई जानता है कि DISTINCT के साथ ऐसी कोई क्वेरी कैसे की जाती है तो कृपया एक नोट जोड़ें!)


2

यहाँ एक सरल दृष्टिकोण है जो प्रत्येक क्वेरी के लिए 2 अलग-अलग समय को प्रिंट करेगा।

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

SET @t1 = GETDATE();
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

या स्टेटिस्टिक्स टाइम (Transact-SQL) सेट करें

SET STATISTICS TIME ON;
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET STATISTICS TIME OFF;

यह बस नीचे दिए गए प्रत्येक कथन को पार्स करने, संकलित करने और निष्पादित करने के लिए आवश्यक मिलीसेकंड की संख्या प्रदर्शित करता है:

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.

1

यह कोई नियम नहीं है

प्रत्येक क्वेरी के लिए .... अलग से अलग और फिर समूह द्वारा प्रयास करें ... प्रत्येक क्वेरी को पूरा करने के लिए समय की तुलना करें और तेज़ का उपयोग करें ...।

अपनी परियोजना में कुछ समय मैं समूह का उपयोग करता हूं और अन्य विशिष्ट होते हैं


0

यदि आपको कोई समूह कार्य (योग, औसत आदि) यदि आप तालिका में संख्यात्मक डेटा जोड़ना चाहते हैं तो नहीं करना है, तो SELECT DISTINCT का उपयोग करें। मुझे संदेह है कि यह तेज़ है, लेकिन मेरे पास इसके लिए कुछ भी दिखाने के लिए नहीं है।

किसी भी स्थिति में, यदि आप गति के बारे में चिंतित हैं, तो कॉलम पर एक इंडेक्स बनाएं।


0

ग्रुप डिस्टेंस की तुलना में सिलेक्ट डिस्टिंक्ट हमेशा एक जैसा या तेज रहेगा। कुछ प्रणालियों (अर्थात ओरेकल) पर, इसे अधिकांश प्रश्नों के लिए DISTINCT के समान ही अनुकूलित किया जा सकता है। दूसरों पर (जैसे SQL सर्वर), यह काफी तेज हो सकता है।


0

यदि समस्या इसे अनुमति देती है, तो EXISTS के साथ प्रयास करें, क्योंकि यह परिणाम मिलते ही समाप्त हो जाता है

SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality

तेजी से प्रतिक्रिया होगी:

SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID )

यह हमेशा संभव नहीं होता है, लेकिन जब आप उपलब्ध होते हैं तो आपको तेजी से प्रतिक्रिया दिखाई देगी।

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