MySQL में, WHERE क्लॉज में कॉलम का क्रम क्वेरी के प्रदर्शन को प्रभावित करता है?


38

मुझे कुछ डेटाबेस प्रश्नों पर प्रदर्शन समस्याएँ हो रही हैं जिनके बड़े परिणाम संभव हैं।

प्रश्न में प्रश्न, मेरे पास तीन ANDखंड में कहां है

क्या खण्डों का क्रम मायने रखता है?

जैसे कि, यदि मैं पहले ASI_EVENT_TIME क्लॉज़ डालता हूं (क्योंकि यह किसी भी क्लॉज़ में से अधिकांश परिणामों को हटा देगा।

क्या इससे क्वेरी पर रन टाइम में सुधार होगा?

: QUERY

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

क्वेरी का विस्तार:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

का उपयोग करते हुए:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

प्रोपेल 1.3

सिम्फनी 1.2.5


ORDER BY शायद व्हाट्सऐप को इतना लंबा समय दे रहा है। "फाइलशॉर्ट का उपयोग करना" बेहद धीमा हो सकता है। मैं आदेश तर्क में आदेश का उपयोग कर की तुलना में तेजी से एक बहुत कुछ कर पाया है।
मैकलमा

मैंने स्टैकओवरफ्लो पर थोड़ी देर पहले (इस साइट से पहले) यही सवाल पूछा था। मुझे वहाँ मिले उत्तरों के लिंक की जाँच करें। stackoverflow.com/questions/3805863/…
स्कॉट

2
@maclema - जब तक कि आपका एप्लिकेशन आपके डेटाबेस की तुलना में कहीं अधिक तेज़ मशीन पर नहीं चल रहा हो, तब तक आपका दावा निश्चित रूप से असत्य है, न कि आपके एप्लिकेशन में उन सभी प्रकार के तर्कहीन बोझ का उल्लेख करना। order byडेटाबेस में है।
जैक डगलस

जवाबों:


24

मुझे ऐसा नहीं लगता है। क्वेरी ऑप्टिमाइज़र पर्याप्त चतुर होना चाहिए।

आप WHERE क्लॉज़ को पुन: व्यवस्थित करने का प्रयास कर सकते हैं और देख सकते हैं कि EXPLAINS आपको प्रत्येक मामले में समान बताता है।


इस क्वेरी को अनुकूलित करने के लिए क्या किया जा सकता है: क्या ASI_EVENT_TIME पर एक सूचकांक है? (इस क्वेरी के लिए मेरे विचार से यह सबसे महत्वपूर्ण है क्योंकि आप इसका उपयोग करके परिणाम भी क्रमबद्ध करते हैं)।

क्या अन्य दो क्षेत्रों (ASI_SEISMO_ID और ASI_ACTIVITY_ID) पर अनुक्रमणिकाएँ हैं?

यदि आप तालिका संरचना को पोस्ट करते हैं तो यह उपयोगी होगा।


मैंने कभी भी घटना के समय का सूचकांक बनाने के लिए नहीं सोचा है। मैं कोशिश करूंगा कि कल देव डीबी पर देखें और देखें कि क्या कोई ध्यान देने योग्य अंतर है।
पैट्रिक

@Patrick इस अनुक्रमणिका का उपयोग करने वाले अन्य सभी प्रश्नों को मानते हुए इस तिथि को अवरोही क्रम में क्रमबद्ध कर रहा है, आप अनुक्रमणिका कुंजी (गतिविधि_seismo_info.ASI_EVENT_TIME) को भी अवरोही क्रम में क्रमबद्ध करना चाहेंगे।
मैट एम

@MattM मुझे नहीं पता था कि आप एक अनुक्रमणिका कुंजी का आदेश दे सकते हैं। बहुत बढ़िया अगर मैं सूचकांक कुंजी का आदेश देता हूं, तो क्या यह अनिवार्य रूप से उस बिंदु के विपरीत दिशा में प्रदर्शन के आदेश को चोट पहुंचाएगा कि यह कोई सूचकांक कुंजी से भी बदतर है?
पैट्रिक

@Patrick आप सही हैं। मेरा मस्तिष्क SQL सर्वर भूमि में फंस गया है। आप MYSQL में सॉर्ट ऑर्डर को निर्दिष्ट कर सकते हैं और यह पार्स करेगा, लेकिन इसे अनदेखा किया गया है। सभी अनुक्रमणिका MYSQL में आरोही क्रम में क्रमबद्ध हैं। गलतफहमी के लिए खेद है।
मैट एम

13

से प्रलेखन :

यदि तालिका में एकाधिक-स्तंभ अनुक्रमणिका है, तो अनुक्रमणिका के किसी भी सबसे ऊपरी उपसर्ग का उपयोग पंक्तियों को खोजने के लिए ऑप्टिमाइज़र द्वारा किया जा सकता है। उदाहरण के लिए, यदि आपके पास (col1, col2, col3) पर तीन-स्तंभ सूचकांक है, तो आपके पास (col1), (col1, col2), और (col1, col2, col3) पर अनुक्रमणित खोज क्षमताएं हैं।

यदि स्तंभ अनुक्रमणिका के बाईं ओर उपसर्ग नहीं बनाता है तो MySQL एक सूचकांक का उपयोग नहीं कर सकता है।

तो हां, यह एक यौगिक सूचकांक में स्तंभों के क्रम के समान होना चाहिए ।


4
यदि तालिका में बाईं ओर के स्तंभों का चयन करने वाला एक बहु-स्तंभ अनुक्रमणिका है - लेकिन आप जिस क्रम का चयन करते हैं वह कोई मायने नहीं रखता है। इसलिए यदि आपके पास इंडेक्स, बी, सी है और आप करते हैं WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'और इंडेक्स अभी भी उपयोग के लिए योग्य है।
टेक्सेलेट'

10

नहीं, इससे कोई फर्क नहीं पड़ता।

आशावादी एसक्यूएल पार्स करने के बाद सीधे सरल परिवर्तनों का एक गुच्छा करता है - यह उनमें से एक है।


8

कहाँ फू और बार

के रूप में ही अनुकूलन

कहाँ बार और फू

तथापि,

कहाँ गैर-बराबर # 1 और गैर-बराबर # 2

दोनों भागों को अनुकूलित नहीं कर सकता। उदाहरण के लिए,

जहाँ एक बीटा 1 और 3 और बी> 17 है

INDEX (a, b) या INDEX (b, a) का अच्छा उपयोग नहीं कर सकता

इसे अलग-अलग वाक्यांश के लिए, किसी भी '=' परीक्षण और एक साथ WHERE क्लॉज में पहले इस्तेमाल किया जाता है, फिर एक गैर - '=' (IN, BETWEEN,>, आदि) संभाला जा सकता है। एक से अधिक प्रभावी ढंग से अनुकूलित नहीं किया जा सकता है।

आपकी क्वेरी में ऐसे 3 खंड हैं।

जैसा कि यह पता चलता है, INDEX (EVENT_TIME) शायद सबसे उपयोगी है - यह ANDs में से किसी एक के साथ मदद करेगा, और इसका उपयोग ORDER BY के लिए "filesort" से बचने के लिए किया जा सकता है।

यदि कोई डुप्लिकेट पंक्तियाँ नहीं हैं (बिल्ली क्यों होगी?), तो DISTINCT से छुटकारा पाएं। वह और भी अधिक प्रयास का कारण बनता है।

प्रदर्शन के प्रश्न पूछते समय कृपया कम समय सारणी और कम तालिका स्थिति प्रदान करें।

अद्यतन ... नए संस्करण (जैसे, MySQL 5.7), कुछ स्थितियों में, IN( list of constants )लगभग जैसा व्यवहार कर सकते हैं =। इसे सुरक्षित चलाने के लिए, इस आदेश के साथ रहें (प्रत्येक भाग वैकल्पिक हो):

  1. की कोई भी संख्या =
  2. कुछ INs
  3. अधिकतम एक सीमा पर।

1

MySQL जहां अनुकूलन डॉक्टर कहता है:

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

  • ...

  • प्रत्येक तालिका में शामिल होने के लिए, तालिका के लिए एक तेज WHERE मूल्यांकन प्राप्त करने के लिए एक सरल WH WH का निर्माण किया जाता है और जल्द से जल्द पंक्तियों को छोड़ने के लिए भी

  • प्रत्येक टेबल इंडेक्स को क्वेर किया जाता है, और सबसे अच्छा इंडेक्स तब तक उपयोग किया जाता है जब तक कि ऑप्टिमाइज़र का मानना ​​नहीं है कि टेबल स्कैन का उपयोग करना अधिक कुशल है । एक समय में, एक स्कैन का उपयोग इस आधार पर किया जाता था कि क्या सबसे अच्छा सूचकांक तालिका के 30% से अधिक का उपयोग करता है, लेकिन एक निश्चित प्रतिशत अब सूचकांक या स्कैन का उपयोग करने के बीच विकल्प का निर्धारण नहीं करता है। ऑप्टिमाइज़र अब अधिक जटिल है और तालिका के आकार, पंक्तियों की संख्या और I / O ब्लॉक आकार जैसे अतिरिक्त कारकों पर इसके अनुमान को आधार बनाता है।

इस तरह क्वेरी ऑप्टिमाइज़र के लिए यह तर्कसंगत है कि HOW- ऑर्डर को कैसे छोड़ा जाए, हमने क्वेरी में कॉलम का उपयोग किया (न केवल MySQL बल्कि SQL एक घोषणात्मक भाषा है और हमें वही करना चाहिए जो हम नहीं चाहते कि हम कैसे चाहते हैं)।

हालाँकि मुझे अभी भी क्वेरी में एक संयुक्त कुंजी के स्तंभों के लिए समान सॉर्ट करना पसंद है लेकिन यह कभी-कभी उदाहरण के लिए अपरिहार्य होता है जब हम ORM या ActiveRecord का उपयोग करते हैं, जैसे कि yii2 जैसे कुछ ढाँचों में, संबंध मानदंड को अनुकूलित करना अंत तक जोड़ा जाएगा। एक "चालू" स्थिति पर, हमें अभी भी एक आवेदन के विभिन्न भागों में QueryBuilders की क्षमताओं की आवश्यकता है।


-2

कोई भी फ़ील्ड जो आपके WHERE / HAVING क्लॉस में उपयोग की जाती है और जिसमें उच्च चयनात्मकता होती है (अद्वितीय मानों की संख्या / रिकॉर्ड की कुल संख्या> 10% ~ 20%) को अवश्य अनुक्रमित किया जाना चाहिए

इसलिए, यदि आपके ASI_EVENT_TIMEकॉलम में कई संभावित मान हैं, तो पहले उन सभी को अनुक्रमित करें। फिर जैसा @ypercube ने बताया, उन्हें पुनर्व्यवस्थित करने का प्रयास करें और देखें कि EXPLAIN आपको क्या बताता है। चारों तरफ एक जैसा होना चाहिए।

इसके अतिरिक्त, आप SQL LIKE फ़िल्टर इंडेक्सिंग पर एक नज़र रखना चाहते हैं । हालांकि यह वह नहीं है जिसके लिए आपको एक उत्तर की आवश्यकता है, लेकिन आप अभी भी इस बारे में सीखेंगे कि हुड के नीचे अनुक्रमण कैसे काम करता है।

* संपादित करें: अनुक्रमण के बारे में अधिक जानने के लिए टिप्पणियों में नीचे दिए गए लिंक का संदर्भ लें।


8
-1 हर कॉलम को इंडेक्स करना एक सर्वोत्तम अभ्यास नहीं है। हर सूचकांक आपको कई तरीकों से खर्च करता है। सुनिश्चित करें कि आप अच्छे अनुक्रमों को चुनें, जिसमें आमतौर पर कई कॉलम होंगे, आमतौर पर चयन और आवृत्ति के क्रम में। यह SQL सर्वर स्लो हो सकता है, लेकिन सूचकांक जानकारी अभी भी मान्य है: sqlskills.com/BLOGS/KIMBERLY/post/…
एरिक हम्फ्री - लॉटहेल्प

@ एरिक हम्फ्रे +1 किम्बर्ली की साइट के स्पष्टीकरण और लिंक के लिए।
मैट एम

आप गलत हैं, स्तंभ पर सूचकांक होने कभी कभी का चयन क्वेरी पर आपके प्रदर्शन को चोट: mysqlperformanceblog.com/2007/08/28/... । आपको कभी भी अंगूठे के नियम का उपयोग नहीं करना चाहिए: कभी-कभी यह काम करता है, कभी-कभी नहीं।
सुमेर

सही है, मैं सहमत हूं। हालाँकि, मान वैधता कम होने की स्थिति में यह मान्य है। पैट्रिक (यह प्रश्न लेखक) द्वारा उपयोग किए जाने वाले डेटा प्रकार को ध्यान में रखते हुए, जो DATETIME है, अनुक्रमण अनुशंसित है। आमतौर पर इस प्रकार के क्षेत्र में मूल्यों का एक बड़ा समूह होता है, जब तक कि विषम स्थिति नहीं होती है जब वह केवल कई संभावित तिथियों का उपयोग करता है। * मैं और अधिक स्पष्ट और मान्य बयान देने के लिए ऊपर दिए गए मेरे उत्तर को संपादित करूंगा।
आँख
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.