क्या LIMIT के उपयोग से प्रदर्शन में सुधार होता है और क्या यह ध्यान देने योग्य है?


11

मैं निम्नलिखित समझना चाहता हूं।
मान लें कि मेरे पास एक जटिल क्वेरी है, जो 5 समूहों के एक समूह को जोड़कर कहती है कि सारांश और क्रम से।
एक तरफ दे क्वेरी ही जैसे अनुक्रमित आदि के लिए किसी भी अनुकूलन
वहाँ कोई महत्वपूर्ण प्रदर्शन का उपयोग कर लाभ है LIMIT? मुझे लगता है कि सभी क्वेरी (और परिणाम) को एलआईएमआईटी लागू होने से पहले संसाधित किया जाना चाहिए , इसलिए परिणामों के सबसेट को पुनः प्राप्त करने के लिए एक एलआईएमटी का उपयोग करना, क्या यह कोई महत्वपूर्ण / ध्यान देने योग्य सुधार प्रदान करता है?


2
मेरा सुझाव है कि आप इस पढ़ा है, उन मामलों को के लिए LIMITदक्षता में सुधार: अनुकूलन LIMIT में प्रश्नों
ypercubeᵀᴹ

जवाबों:


10

यदि आप LIMITप्रदर्शन में सुधार के लिए लाभ लेना चाहते हैं , तो आपको जरूरत है

  • उस डेटा को समझें जिसे आप पुनर्प्राप्त कर रहे हैं
  • स्तंभों के सही अनुक्रम को उचित अनुक्रमित करना
  • क्वेरी को फिर से शुरू करने की जिम्मेदारी लें
  • LIMITपहले उपयोग कर रहा हैJOIN

यदि आप उन्हें ऑर्केस्ट्रेट कर सकते हैं तो ये सिद्धांत बहुत आगे बढ़ सकते हैं।

मैंने इस YouTube वीडियो को देखकर इन अवधारणाओं को सीखा (फ्रेंच उच्चारण के माध्यम से ध्यान से सुनो)

मैंने उन अवधारणाओं का उपयोग कुछ टेबलों से शीर्ष 40 लेख प्राप्त करने के बारे में एक बहुत ही कठिन स्टैकऑवरफ्लो प्रश्न का उत्तर देने के लिए किया: 12 मई, 2011: ज्वाइन टेबल से एक एकल पंक्ति प्राप्त करना

में उस प्रश्न का मेरा उत्तर (16 मई, 2011) , मैं निम्न क्वेरी लिखा था और यह अच्छी तरह से परीक्षण:

SELECT
  AAA.author_id,
  AAA.date_created,
  IFNULL(BBB.title,'<NO_TITLE>') title,
  IFNULL(CCC.filename,'<NO-IMAGE>') filename,
  IFNULL(CCC.date_added,'<NO-IMAGE-DATE>') image_date
FROM
(
  SELECT
    AA.id,
    AA.date_added,
    BB.author_id,
    BB.date_created
  FROM
  (
    SELECT
      A.id,IFNULL(MAX(B.date_added),'1900-01-01 00:00:00') date_added
      FROM (SELECT id FROM articles ORDER BY date_created DESC LIMIT 40) A
      LEFT JOIN article_images B ON A.id = B.article_id
      GROUP BY A.id
  ) AA
  INNER JOIN articles BB USING (id)
) AAA
LEFT JOIN article_contents BBB ON AAA.id=BBB.article_id
LEFT JOIN article_images CCC
ON (AAA.id=CCC.article_id AND AAA.date_added=CCC.date_added)
ORDER BY AAA.date_created DESC;

कृपया क्वेरी के साथ लाइन को नोटिस करें LIMIT

      FROM (SELECT id FROM articles ORDER BY date_created DESC LIMIT 40) A

इस उपश्रेणी को तीन स्तरों गहरे दफनाया गया है। इसने मुझे पिछले 40 लेखों का उपयोग करने की अनुमति दी LIMIT। फिर, मैंने बाद में आवश्यक जॉइन किया।

सीख सीखी

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

तो (A [LEFT] JOIN B) LIMIT 100के बराबर है (A LIMIT 100) [LEFT] JOIN (B LIMIT 100)? जहां [LEFT] JOINबाहरी या भीतरी जुड़ने का मतलब है
जिम

यह अधिक पसंद है (A LIMIT 100) [LEFT] JOIN B। विचार का उपयोग LIMITपरिणाम के आकार को निर्धारित करने के लिए यथाशीघ्र करना है। मैं LEFT JOINइसके बजाय भी उपयोग करता हूं INNER JOINक्योंकि LEFT JOINबाईं ओर कुंजियों के क्रम को संरक्षित करेगा।
रोलैंडमाइसीडीडीबीए

@ जय नहीं, वे नहीं हैं। कभी-कभी, वे इस तरह से होते हैं: (A LEFT JOIN B) GROUP BY A.pk LIMIT 100आमतौर पर फिर से लिखा जा सकता है (A LIMIT 100) LEFT JOIN B GROUP BY A.pk(यहां कोई भी शामिल नहीं है, आंतरिक जोड़ के साथ वे समकक्ष नहीं होंगे।) रोलैंडो का उदाहरण बिल्कुल ऐसा ही मामला है।
ypercube y

@ypercube: तो भीतरी जोड़ के साथ वहाँ कुछ करने के लिए फायदा नहीं है?
जिम

मैं रॉलैंडो द्वारा उल्लिखित पुनर्लेखन की रणनीति का उल्लेख कर रहा था। JOINs और LIMIT के साथ एक क्वेरी के रूप में अच्छी तरह से लाभ हो सकता है। या नहीं। निर्भर करता है।
ypercube y

2

जब किसी क्वेरी को निष्पादित किया जाता है, तो इसे पहले एक योजना में अनुवादित किया जाता है जो कई ऑपरेटरों से बना होता है। ऑपरेटरों के दो बुनियादी प्रकार हैं: ब्लॉकिंग और नॉन-ब्लॉकिंग। एक गैर-ब्लॉकिंग ऑपरेटर अपने बच्चे या उसके द्वारा अनुरोधित प्रत्येक पंक्ति के लिए अपने बच्चे या बच्चों से एक पंक्ति (या कुछ पंक्तियाँ) प्राप्त करता है। दूसरी तरफ एक ब्लॉकिंग ऑपरेटर को अपने सभी बच्चों के पूरे पंक्ति सेट को पढ़ना और संसाधित करना पड़ता है, इससे पहले कि वह कोई आउटपुट दे सके।

सॉर्ट एक विशिष्ट ब्लॉकिंग ऑपरेटर है। तो आदेश के साथ एक चयन एक सीमा से ज्यादा लाभ नहीं करता है। हालांकि, आरडीबीएमएस हैं जो एक छँटाई एल्गोरिथ्म का उपयोग कर सकते हैं जिन्हें कम मेमोरी की आवश्यकता होती है और एक सीमा खंड प्रदान किए जाने पर तेजी से होता है। यह इस मामले में पर्याप्त है कि वर्तमान में केवल पहली पंक्तियों को संग्रहीत करें और उन्हें स्मृति से बाहर ले जाएं क्योंकि पहले की पंक्तियां साथ आती हैं। यह एक महत्वपूर्ण प्रदर्शन लाभ हो सकता है। हालाँकि, मुझे 100% यकीन नहीं है कि MySQL में वह क्षमता है।

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


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

उपस्थित क्वेरी और अनुक्रमित के आधार पर, GROUP BYसंभावित रूप से एक योजना हो सकती है जो जाती है जिसमें अवरुद्ध ऑपरेटर शामिल नहीं हैं।
सेबस्टियन मेन

0

मेरे मामले में, मैं हां कह सकता हूं , भले ही मुझे (अभी भी) समझ में क्यों न आए।

SELECT g0_.id AS id_0, COUNT(a1_.id_tarifs) AS sclr_1
FROM groupe_jardinerie g0_
INNER JOIN articles_tarifs a1_
  ON (a1_.groupe_jardinerie_id = g0_.id)
WHERE g0_.centrale_id = 511
  AND a1_.date_fin_tarif >= '2018-01-29 10:46:35'
GROUP BY g0_.id;

(result set)

8 rows in set (**18.14 sec**)

समय पर ध्यान दें: 18 सेकंड। एक बड़ी सीमा के साथ एक ही अनुरोध:

SELECT g0_.id AS id_0, COUNT(a1_.id_tarifs) AS sclr_1 
FROM groupe_jardinerie g0_
INNER JOIN articles_tarifs a1_
  ON (a1_.groupe_jardinerie_id = g0_.id)
WHERE g0_.centrale_id = 511 
  AND a1_.date_fin_tarif >= '2018-01-29 10:46:35'
GROUP BY g0_.id
LIMIT 100000000000;

(exact same result set)

8 rows in set (**1.32 sec**)

दस गुना से अधिक तेज !!!

EXPLAIN दोनों अनुरोधों के लिए समान परिणाम देता है।

+----+-------------+-------+------------+--------+---------------------------------------------------+---------+---------+------------------------------+--------+----------+----------------------------------------------+
| id | select_type | table | partitions | type   | possible_keys                                     | key     | key_len | ref                          | rows   | filtered | Extra                                        |
+----+-------------+-------+------------+--------+---------------------------------------------------+---------+---------+------------------------------+--------+----------+----------------------------------------------+
|  1 | SIMPLE      | a1_   | NULL       | ALL    | IDX_438010BBC10784EF                              | NULL    | NULL    | NULL                         | 795135 |    33.33 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | g0_   | NULL       | eq_ref | PRIMARY,IDX_9CA5CF6758A1D71F,IDX_9CA5CF67670C757F | PRIMARY | 4       | phs.a1_.groupe_jardinerie_id |      1 |    50.00 | Using where                                  |
+----+-------------+-------+------------+--------+---------------------------------------------------+---------+---------+------------------------------+--------+----------+----------------------------------------------+

लिमिट को केवल परिणाम सेट को सीमित करने के लिए हस्तक्षेप करना चाहिए (यानी, अगर मैं एक लिमिट 4 करता हूं, तो मुझे उपरोक्त परिणाम सेट की पहली 4 पंक्तियां मिलीं)।


भयानक, आप किस संस्करण का उपयोग कर रहे हैं और क्या आप एक सरलीकृत परीक्षण केस बना सकते हैं?
इवान कैरोल

1
आपका उत्तर किसी भी नए लाभ के लिए साबित नहीं होता है LIMIT। आपका 1 क्वेरी परिणाम सेट करते हुए 18 सेकंड में चलता है। पहले क्वेरी के कारण, InnoDB बफ़र पूल में 2nd क्वेरी में सभी डेटा पहले से ही कैश्ड है, इसलिए निश्चित रूप से 2nd क्वेरी को तेज़ करना होगा, भले ही आप mysql को पुनरारंभ करते हों, 1 क्वेरी को चलाते हैं, mysql को पुनरारंभ करते हैं, और 2nd को चलाते हैं। क्वेरी, आपको एक ही परिणाम मिलेगा। । के लिए एक बेहतर परिणाम होने LIMITसे ही कर सकते हैं: 1) LIMITसे पहले JOIN, 2) सॉर्ट क्रम में ASCया DESC
रोलैंडमाइसीडीडीबीए

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