2011-06-23 20 views
5

मैं एक MySQL क्वेरी नोबी हूं इसलिए मुझे यकीन है कि यह एक स्पष्ट उत्तर के साथ एक प्रश्न है।MySQL समूह द्वारा और हैविंग

लेकिन, मैं इन दो प्रश्नों को देख रहा था। क्या वे अलग-अलग परिणाम सेट वापस कर देंगे? मैं समझता हूं कि सॉर्टिंग प्रक्रिया अलग-अलग शुरू होगी, लेकिन मेरा मानना ​​है कि वे वही परिणाम पहले प्रश्न के साथ थोड़ा अधिक कुशल होने के साथ वापस कर देंगे?

क्वेरी 1: होने, तो और

SELECT user_id 
FROM forum_posts 
GROUP BY user_id 
    HAVING COUNT(id) >= 100 
    AND user_id NOT IN (SELECT user_id FROM banned_users) 

क्वेरी 2: कहां, तो

SELECT user_id 
FROM forum_posts 
WHERE user_id NOT IN(SELECT user_id FROM banned_users) 
GROUP BY user_id 
    HAVING COUNT(id) >= 100 

उत्तर

1

होने वास्तव में पहली क्वेरी कम कुशल हो जाएगा (HAVINGWHERE के बाद लागू)।
अद्यतन

उदाहरण देकर स्पष्ट करना चाहते हैं कि आपके प्रश्नों ([बहुत] सरलीकृत संस्करण) क्रियान्वित कर रहे हैं कुछ छद्म कोड।
पहले क्वेरी:
1. SELECT user_id FROM forum_posts
2. SELECT user_id FROM banned_user
3. समूह, गिनती, आदि
4. पहला परिणाम सेट करता है, तो वे दूसरे

दूसरा क्वेरी
में प्रस्तुत कर रहे हैं से रिकॉर्ड को शामिल न करें 1. SELECT user_id FROM forum_posts
2. SELECT user_id FROM banned_user
3. पहला परिणाम सेट करता है, तो वे दूसरे
में प्रस्तुत कर रहे हैं से रिकॉर्ड को शामिल न करें 4. समूह, गिनती, आदि

चरणों का क्रम 1,2 महत्वपूर्ण नहीं है, mysql जो कुछ भी सोचता है वह चुन सकता है। महत्वपूर्ण अंतर चरण 3,4 में है। GROUP BY के बाद लागू किया जा रहा है। ग्रुपिंग आम तौर पर शामिल होने से अधिक महंगा है (रिकॉर्ड्स को छोड़कर इस मामले में ऑपरेशन में शामिल होने पर विचार किया जा सकता है), इसलिए कम रिकॉर्ड को समूह में बेहतर प्रदर्शन करना है।

+0

महान, धन्यवाद! दिलचस्प है, मुझे कुछ परीक्षण चलाने होंगे। मैंने और अधिक कुशलता से सोचा क्योंकि पहले से समूहित होने के बाद banned_users भाग में नहीं तुलना करने के लिए कम रिकॉर्ड हैं? यदि इसका कोई औचित्य हो। – kimmothy

+0

हां, उस स्थिति का परीक्षण केवल समूह द्वारा किए गए परिणामों के समूह के लिए किया जाएगा, बिलकुल नहीं। – aorcsik

+0

@ किममोथी: 'IN IN 'में उपकुंजी को वास्तव में केवल एक बार निष्पादित करने की आवश्यकता है। – a1ex07

0

होने की स्थिति द्वारा परिणाम वर्गीकृत किया पर लागू होते हैं, और user_id द्वारा समूह के बाद से, उनके संभावित मानों की सभी वर्गीकृत किया परिणाम में मौजूद रहेंगे, इसलिए user_id हालत रखने महत्वपूर्ण नहीं है।

+0

रखरखाव महत्वपूर्ण है। यदि 'WHERE' लागू किया गया है, तो समूह कम पंक्तियों (यहां तक ​​कि शून्य) में किया जाता है, इसलिए COUNT() को केवल उन पंक्तियों के लिए गणना की जानी चाहिए। यदि यह 'हैविंग' खंड के लिए छोड़ा गया है, तो समूह (और गिनती) सभी पंक्तियों पर किया जाता है और फिर स्थिति की जांच की जाती है। परिणाम: यदि प्रतिबंधित उपयोगकर्ता सभी उपयोगकर्ताओं का एक बड़ा प्रतिशत हैं, तो अंतर गति बहुत अच्छी होगी (आनुपातिक रूप से) –

+0

बेशक गति में अंतर केवल तभी मौजूद होता है जब अनुकूलक 2 प्रश्नों के लिए अलग-अलग योजनाओं के साथ उत्पन्न होता है। –

+0

इसे इंगित करने के लिए धन्यवाद, मैंने वास्तव में यहां उत्तरों से बहुत कुछ सीखा। :) – aorcsik

-1

नहीं, यह समान परिणाम नहीं देता है।

क्योंकि पहली क्वेरी गिनती (आईडी) हालत से रिकॉर्ड फिल्टर करेगा

एक और क्वेरी फिल्टर रिकॉर्ड और फिर खंड होने लागू होते हैं। क्योंकि यह ग्रुप द्वारा और होने के लिए अभिलेखों की संख्या को कम करती है

दूसरा क्वेरी सही ढंग से

+2

चूंकि आप कह रहे हैं कि परिणाम अलग होंगे, आप शायद ही दावा कर सकें कि कौन सी समस्या हल हो रही है, इससे पहले कि आप सही ढंग से लिखे गए हों।कम से कम, वे दोनों सही * वाक्य रचनात्मक * हैं। और, वास्तव में, परिणाम भी वही होंगे। यह दक्षता है कि वे अलग-अलग होंगे। –

+0

@Andriy: क्या आप सुनिश्चित हैं कि दक्षता में अंतर है? –

+0

@ypercube: मुझे उम्मीद है कि हैविंग के बाद मूल्यांकन करने की उम्मीद है, और वास्तव में, ग्रुप बाय के बाद भी (जो, मुझे लगता है कि, इसके बाद भी गणना की जाती है)। इस प्रकार पहली क्वेरी अनावश्यक रूप से उन पंक्तियों के लिए गणना की गणना करेगी जिन्हें बाद में 'user_id' के आधार पर त्याग दिया जाएगा। दूसरा एकत्रीकरण से पहले 'user_id' पर फ़िल्टर करता है। –

0

लिखा है मेरे लिए, दूसरा क्वेरी और अधिक कुशल है।

वैकल्पिक रूप से, आप में का उपयोग कर से बचने के लिए निम्न क्वेरी कोशिश कर सकते हैं:

SELECT `fp`.`user_id` 
FROM `forum_posts` `fp` 
LEFT JOIN `banned_users` `bu` ON `fp`.`user_id` = `bu`.`user_id` 
WHERE `bu`.`user_id` IS NULL 
GROUP BY `fp`.`user_id` 
HAVING COUNT(`fp`.`id`) >= 100 

आशा इस मदद करता है।

0

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

मेरे opininion कि वहाँ दक्षता (गति) में एक अंतर है, केवल अगर विभिन्न योजनाओं 2 प्रश्नों के लिए साथ अनुकूलक पैदावार हो जाएगा। मुझे लगता है कि नवीनतम MySQL संस्करणों के लिए ऑप्टिमाइज़र या तो क्वेरी के लिए एक ही योजना को खोजने के लिए पर्याप्त स्मार्ट हैं इसलिए पर कोई अंतर नहीं होगा, लेकिन निश्चित रूप से कोई भी परीक्षण कर सकता है या EXPLAIN के साथ उत्तेजना योजनाओं को देख सकता है या 2 प्रश्नों को चला सकता है कुछ टेस्ट टेबल के खिलाफ।

मैं किसी भी मामले में दूसरे संस्करण का उपयोग केवल सुरक्षित खेलने के लिए करता हूं।


मुझे उस जोड़ें:

  • COUNT(*) आमतौर पर MySQL में COUNT(notNullableField) तुलना में अधिक कुशल है। जब तक कि भविष्य में MySQL संस्करणों में तय नहीं किया जाता है, लागू होने पर COUNT(*) का उपयोग करें।

इसलिए, आप भी उपयोग कर सकते हैं:

SELECT user_id 
FROM forum_posts 
WHERE user_id NOT IN 
    (SELECT user_id FROM banned_users) 
GROUP BY user_id 
HAVING COUNT(*) >= 100 
  • वहाँ भी GROUP BY लागू करने से पहले ही (NOT IN करने के लिए) उप परिणाम प्राप्त करने के अन्य तरीकों।

LEFT JOIN/NULL का उपयोग करना:

SELECT fp.user_id 
FROM forum_posts AS fp 
    LEFT JOIN banned_users AS bu 
    ON bu.user_id = fp.user_id 
WHERE bu.user_id IS NULL 
GROUP BY fp.user_id 
HAVING COUNT(*) >= 100 

NOT EXISTS का उपयोग करना:

SELECT fp.user_id 
FROM forum_posts AS fp 
WHERE NOT EXISTS 
    (SELECT * 
    FROM banned_users AS bu 
    WHERE bu.user_id = fp.user_id 
) 
GROUP BY fp.user_id 
HAVING COUNT(*) >= 100 

3 तरीकों में से कौन सा तेजी से होता है अपने तालिका आकार और अन्य कारकों का एक बहुत पर निर्भर करता है, तो सबसे अच्छा परीक्षण करने के लिए है आपके डेटा के साथ।

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