2011-12-25 6 views
6

निम्न क्वेरी से (~ साथ 6k पंक्तियों 0.7 सेकंड) अपेक्षाकृत धीमी हैMySQL द्वारा/क्रम धीमा समूह

SELECT items.*, COUNT(transactions.ID) 
    FROM items 
    INNER JOIN users ON (items.USER = users.ID) 
    LEFT JOIN transactions ON (items.id = transactions.item) 
    WHERE items.ACTIVE = 1 
    AND items.DELETED_AT IS NULL 
    GROUP BY items.ID 
    ORDER BY items.DATE DESC 
    LIMIT 20 

लेकिन जब items.ID DESC बजाय items.DATE द्वारा आदेश दिया नाटकीय रूप से गति। शामिल लेनदेन एक बड़ी मेज (~ 250k पंक्तियों) के लिए है और एक से कई है। दिनांक कॉलम में एक सूचकांक है।

क्या ORDER BY के प्रदर्शन को सामान्य रूप से सुधारने का कोई तरीका है?

संपादित करें: आइटम्स.user, accounts.item, और items.date पर अनुक्रमणिका। वस्तुओं में 49 कॉलम, उपयोगकर्ता 76 और लेनदेन 17.

+3

क्या आप तीन तालिकाओं के लिए स्कीमा और विशेष रूप से इंडेक्स प्रदान कर सकते हैं? – TetonSig

+0

एकमात्र चीज जिसे मैं सोच सकता हूं वह सबसे पहले आपके WHERE क्लॉज द्वारा फ़िल्टर किए गए आइटमों का चयन कर रहा है और उपशीर्षक में दिनांक के अनुसार आदेश दिया गया है, (या एक दृश्य में, यदि MySQL subqueries में ORDER द्वारा समर्थित नहीं है) और फिर एक संलग्न क्वेरी में आपका जुड़ता है (मैं इसे एक उत्तर के रूप में नहीं लिख रहा हूं क्योंकि एस सट्टा जवाबों को हतोत्साहित करता है।) –

+0

क्या आपने 'GROUP BY' में 'आइटम्स.डेट' को शामिल करने का प्रयास किया है (पहली स्थिति में भी)? –

उत्तर

5

इंडेक्स ORDER BY खंडों के प्रदर्शन को प्रभावित कर सकते हैं। यह MySQL manual page शायद आपके समय के लायक है। अनिवार्य रूप से, यदि आप उस कॉलम द्वारा ऑर्डर करते हैं जो इंडेक्स का हिस्सा है जो MySQL क्वेरी के लिए उपयोग करता है, तो MySQL डेटा के बजाए सॉर्ट के लिए इंडेक्स का उपयोग कर सकता है।

आपकी विशेष क्वेरी में, तथ्य यह है कि DATE कॉलम में कोई फर्क नहीं पड़ता है, क्योंकि उस अनुक्रमणिका का शायद आपकी क्वेरी में उपयोग नहीं किया जा रहा है। आपके WHERE कथन में items.ACTIVE और items.DELETED_AT शामिल हैं, और यदि उन कॉलम में एक इंडेक्स है जिसका उपयोग WHERE के लिए किया जा रहा है जिसमें DATE कॉलम शामिल नहीं है, तो MySQL DATE द्वारा सॉर्ट करने के लिए इंडेक्स का उपयोग नहीं कर सकता है, और संभवतः एक फ़ाइल का सहारा ले रहा है तरह।

यदि आप एक इंडेक्स के साथ आ सकते हैं जिसका उपयोग WHERE और ORDER BY दोनों द्वारा किया जा सकता है, तो आपको ऑप्टिमाइज़ेशन बढ़ावा मिलेगा। इस मामले में, items.ACTIVE कम कार्डिनालिटी कॉलम की तरह लगता है, इसलिए items.DELETED_AT मानना ​​एक तारीख है, मैं शायद उस तालिका के लिए INDEX(DELETED_AT,DATE) जैसे इंडेक्स का प्रयास करूंगा।

EXPLAIN SELECT... का उपयोग करें कि वहां क्या हो रहा है, इसके बारे में और जानने के लिए, आपको कुछ और अंतर्दृष्टि मिल सकती हैं।

0

ये ऐसी चीजें हैं जो COULD (गारंटी नहीं पढ़ी जा सकती हैं) मदद कर सकती हैं।

  1. आइटम पर * हटाएं। * और प्रत्येक फ़ील्ड को व्यक्तिगत रूप से सूचीबद्ध करें। 49 कॉलम बहुत कुछ है क्या आपको वास्तव में उन सभी की आवश्यकता है?
  2. आम तौर पर इंजन मानदंडों को सीमित करने पर विचारों को अनुकूलित करता है। शायद इंजन द्वारा उपयोग की जाने वाली योजना यह नहीं कर रही है (योजना के परिणामों को समझाने की आवश्यकता है) ताकि जहां से क्लॉज को फिर से व्यवस्थित किया जा सके और द्वारा इस पर विचार करने के लिए मई (संभवतः) सहायता में शामिल हो। (नीचे देखें)
  3. तालिका आंकड़ों के पुनर्निर्माण अगर कई अद्यतन, सम्मिलित करें, हटाता समय के साथ हुई है, यह संभव है तालिका के आंकड़ों को बंद कर रहे हैं और हर तालिका

के लिए rebuilt की जरूरत है।

SELECT items.[list fields], COUNT(transactions.ID) 
    FROM items 
    INNER JOIN users ON (items.USER = users.ID) 
     AND items.Active=1 
     AND items.DELETED_AT is Null 
    LEFT JOIN transactions ON (items.id = transactions.item) 
    GROUP BY items.ID 
    ORDER BY items.DATE DESC 
    LIMIT 20 
2

चुनें * से एक्स आदेश आईडी DESC

ऊपर क्वेरी सही काम करता है के रूप में, मैं इसे एक बहुत लंबे डेटाबेस में इस्तेमाल किया है (wp_users कहां आईडी सीमा 0,10 द्वारा 1 ग्रुप से चुनें *) ।यह 10 या (xx) वस्तुओं की सूची द्वारा आदेश दिया गया है जो हम आंतरिक चयन क्वेरी से प्राप्त कर रहे हैं, इसलिए यह बहुत तेज़ !!