2015-09-17 8 views
5

मेरे पास एक प्रश्न है जो डीबी से दूसरी उच्चतम तारीख के रिकॉर्ड प्राप्त करता है। मेरी क्वेरी अच्छी तरह से काम कर रही है लेकिन निष्पादन में बहुत अधिक समय लगता है। मैं अपनी क्वेरी को जल्दी से कैसे निष्पादित कर सकता हूं।क्यों मेरी mysql क्वेरी धीमी गति से काम कर रही है?

+2

एक अच्छा सवाल है। क्या गलत है यह देखने के लिए अपनी क्वेरी से पहले EXPLAIN का उपयोग करें, या परिणाम –

+0

@BerndBuffen मैं इसे आजमाऊंगा – sunny

+0

परिणाम पोस्ट करें तो मैं –

उत्तर

2

मैं दूसरों की तुलना में इसमें कुछ समय लग जा रहा हूँ अलग ढंग से ... मैं स्पष्ट अनुक्रमण अनुकूलन जो सभी अपने मिलती खोज के लिए प्राथमिक कुंजी पर कर रहे हैं में कुछ कमी या अलग कर रहा हूँ - अपने मापदंड सही है?

यहां मेरा मतलब है ... आपका अंतिम WHERE खंड ..

WHERE 
     r.client_id IN (SELECT opinion_id 
          FROM pacra_client_opinion_relations 
          WHERE client_id = 50) 

आप एक CLIENT_ID एक OPINION_ID के एक चयनित परिणाम में किया जा रहा है, लेकिन केवल client_id = 50 के लिए राय क्या Opinion_id के संदर्भ है की तलाश के लिए पूछ रहे हैं। ग्राहक की

स्पष्टीकरण अपनी मेज "pacra_client_opinion_relations" से राय बनाम

Opinion_ID Client_ID Other... 
1    28   ... 
2    35   ... 
3    50   ... 
4    2   ... 
5    50   ... 
6    6   ... 
7    50   ... 
8    4   ... 

नीचे के रूप में नमूना डेटा देखते चलें तो आपकी क्वेरी client_id = 50 के लिए सभी OPINION_IDs है, तो आप वापसी होगी OPINION_ID # से 3, 5 और 7. चूंकि आपका क्लॉज राय के चयन में CLIENT_ID के लिए पूछ रहा है, अब आप क्लाइंट 3, 5 और 7 के लिए डेटा ले रहे हैं और क्लाइंट # 50 के साथ कुछ भी करने के लिए नहीं है जिसे आपने मूल रूप से देखना शुरू कर दिया था।

इसके अलावा ... यदि आप केवल "Client_ID = 50" से चीजों के लिए देख रहे हैं, तो आपकी पिछली क्वेरी SECOND को सबसे हालिया अधिसूचना दिनांक में प्राप्त करने का प्रयास कर रही है, तो आप सभी क्लाइंट से पूछताछ कर रहे हैं। यदि आप "Client_ID = 50" के लिए कोई क्लॉज जोड़ते हैं, तो आप केवल उन सभी को प्राप्त करेंगे, न कि दूसरी क्लाइंट की हालिया अधिसूचना।

आंतरिक MAX() से MAX() से कम स्पष्ट करने के लिए। रेटिंग पूर्व डेटा आप निम्नलिखित मिलेगा ...

og_ratings (assuming this data is pre-sorted per client for sample purposes) 
client_id notification_date 
13   Sep 5  <- You want THIS entry if it was client 13 included 
13   Sep 14  <- Most recent for client 13 
28   Sep 1 
28   Sep 8 
28   Sep 10  <- You want THIS entry if client 28 included 
28   Sep 11  <- Most recent for client 28 
29   Sep 4  <- You want THIS entry if client 29 included 
29   Sep 11  <- Most recent for client 29 
43   Sep 16  <- Most recent for client 43 and no prior, 
         this would never show as only one entry for client 
50   Sep 2 
50   Sep 9 
50   Sep 12  <- You want THIS entry for client 50 
50   Sep 15  <- Most recent for client 50 

नमूना डेटा के आधार पर, आप प्राप्त करेंगे ... विभिन्न ग्राहकों नवीनतम दिनांकों

client_id notification_date 
13   Sep 5 
28   Sep 10 
29   Sep 4 
50   Sep 12 

सब तो से अलग 2 हो सकता था आपने अपनी बाहरी क्वेरी में देखभाल की थी, ग्राहक 50 था, और आपके वास्तविक डेटा में सैकड़ों ग्राहक थे (या यहां तक ​​कि हजारों क्लाइंट), आप सभी क्लाइंट से पूछताछ कर रहे हैं। आप विशेष रूप से ग्राहक 50 के माध्यम से के लिए अपने भीतर क्वेरी सीमित हो सकती है ...

og_ratings r INNER JOIN (
    SELECT 
     client_id, 
     max(notification_date) notification_2nd_date 
    FROM 
     og_ratings 
    WHERE 
     (client_id, notification_date) 
     NOT IN (SELECT client_id, max(notification_date) 
        FROM og_ratings 
        GROUP BY client_id) 
    GROUP BY 
     client_id 
    ORDER BY 
     client_id DESC 

लिए समायोजित किया जा सकता है ...

og_ratings r INNER JOIN (
    SELECT 
     client_id, 
     max(notification_date) notification_2nd_date 
    FROM 
     og_ratings 
    WHERE 
     client_id = 50 <--- ADDED TO WHERE CLAUSE for CLIENT 50 ONLY 
     AND (client_id, notification_date) 
     NOT IN (SELECT client_id, max(notification_date) 
        FROM og_ratings 
        WHERE client_id = 50 <--- ADDED HERE TOO FOR CLIENT 50 
        GROUP BY client_id) 
    GROUP BY 
     client_id 
    ORDER BY 
     client_id DESC 

और यह केवल सभी के लिए ग्राहक 50 के लिए एकल रिकॉर्ड वापसी होगी दिनांकों बनाम ग्राहकों

client_id notification_date 
50   Sep 12 

अन्त में, और MySQL प्रश्नों की पेशकश की कई बार में, मैं कीवर्ड STRAIGHT_JOIN का उपयोग कर की पेशकश की है। यह मूल रूप से आपके द्वारा बताए गए क्रम में क्वेरी करने के लिए MySQL को बताता है ... कभी-कभी जब (जैसे आपका केस), आपके पास लुकअप टेबल का एक गुच्छा है, तो यह आपके लिए सोचने की कोशिश कर रहा है और कम से कम एक लुकअप टेबल का उपयोग कर सकता है रिकॉर्ड मायने रखता है (या क्या/हालांकि) यह क्वेरी लागू करता है।

चयन STRAIGHT_JOIN ... क्वेरी

अगर मैं अपने मान्यताओं पर सही कर रहा हूँ के बाकी, एक अधिक सरलीकृत क्वेरी भी किया जा सकता है, मैं सिर्फ अलग टुकड़ों है कि मैं के रूप में संदिग्ध देख समझाने की कोशिश कर रहा हूँ ... आखिरकार, जैसा कि आप मेरे पास नमूना डेटा देखते हैं, यदि आप इस पर नमूना डेटा तैयार कर सकते हैं और आपके पास जो कुछ भी है, उसके भविष्य के बारे में भविष्य में तैयार हो सकता है ...

+0

मेरा 'client_id' एकाधिक 'opinion_id' है। आपका जवाब अच्छा है लेकिन मेरे लिए समझना मुश्किल है क्योंकि मैं कोडिंग में बहुत नया हूं। – sunny

+0

@sunny, मेरे उत्तर में संशोधन ... एक नज़र डालें और देखें कि क्या स्पष्टीकरण आपको और मेरी डेटा की व्याख्या और आप जो खोज रहे हैं, उसकी मदद करते हैं। – DRapp

+0

लेकिन मुझे क्लाइंट_आईडी के खिलाफ सभी रिकॉर्ड चाहिए। जैसा कि आप जानते हैं कि मेरे क्लाइंट_आईडी में कई राय_आईडी हैं। मैं client_id के खिलाफ राय_आईडी के सभी रिकॉर्ड लाने के लिए चाहता हूँ। इसके लिए आप मेरी मदद कर सकते हैं? – sunny

0

क्षेत्रों नीचे प्रदर्शन-

Table : og_ratings 

notification_date 
pacra_action 
pacra_outlook 
pacra_lterm 
pacra_sterm 

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

यदि आप इंडेक्स विवरण के साथ सभी टेबल संरचना दिखाते हैं तो बेहतर तरीके से आपकी मदद कर सकते हैं। सूचकांक निर्माण के लिए

अद्यतन:

alter table og_ratings 
add index idx_pacra_action(pacra_action), 
add index idx_pacra_outlook(pacra_outlook), 
add index idx_pacra_lterm(pacra_lterm), 
add index idx_pacra_sterm(pacra_sterm); 

2 क्वेरी तर्क में परिवर्तन के कारण संपादित करें:

वास्तव में आपकी क्वेरी तार्किक है सही रूप में आप में 2 पैरामीटर प्रदान करने के प्रयास कर रहे हैं नहीं है where (client_id, notification_date) not in (SELECT client_id, MAX(notification_date) FROM og_ratings GROUP BY client_id)

जैसे खंड में नहीं, तो नीचे दिए गए प्रश्न की जांच करें यदि यह आपको वांछित परिणाम प्रदान करता है और तेजी से होना चाहिए-

SELECT r.client_id,c.id,t.id,a.id,o.id,c.name AS opinion, r.notification_date, t.title AS ttitle,a.title AS atitle,o.title AS otitle, l.title AS ltitle, s.title AS stitle, r.opinion_id, pc.id, r.pr_client_id AS pr_client, pc.address, pc.liaison_one, city.id, pc.head_office_id, city.city, pc.title AS cname 
FROM (SELECT a.client_id, a.notification_date, a.rating_type_id, a.pacra_action, a.pacra_outlook, a.pacra_lterm, a.pacra_sterm, a.opinion_id, a.pr_client_id 
FROM (SELECT t.client_id, t.notification_date, t.rating_type_id, t.pacra_action, t.pacra_outlook, t.pacra_lterm, t.pacra_sterm, pr.opinion_id, pr.client_id AS pr_client_id, 
       CASE 
       WHEN @category != t.client_id THEN @rownum := 1 
       ELSE @rownum := @rownum + 1 
       END AS rank, 
       @category := t.client_id AS var_category 
      FROM og_ratings t 
      JOIN pacra_client_opinion_relations pr ON pr.opinion_id = r.client_id 
      JOIN (SELECT @rownum := NULL, @category := '') r 
      WHERE pr.client_id = 50 
      ORDER BY t.client_id,t.notification_date DESC) a 
     WHERE x.rank=2) r 
LEFT JOIN og_companies c ON r.client_id = c.id 
LEFT JOIN og_rating_types t ON r.rating_type_id = t.id 
LEFT JOIN og_actions a ON r.pacra_action = a.id 
LEFT JOIN og_outlooks o ON r.pacra_outlook = o.id 
LEFT JOIN og_lterms l ON r.pacra_lterm = l.id 
LEFT JOIN og_sterms s ON r.pacra_sterm = s.id 
LEFT JOIN pacra_clients pc ON pc.id = r.pr_client_id 
LEFT JOIN city ON city.id = pc.head_office_id 

मैं इस क्वेरी निष्पादित नहीं की है, तो इतना है कि मैं इसे सही कर सकते हैं अगर आप किसी भी सिंटेक्स त्रुटि आदि मिलता है तो आप एक sqlfiddle बना सकते हैं।

+0

साथ मेरे सवाल का आपका क्या मतलब अद्यतन – sunny

+4

@sunny https://dev.mysql.com/doc/refman/5.0/en/show-index.html आपका जीवन एक बहुत आसान हो जाएगा खोज इंजन :) – Jonast92

+0

@ Jonast92 मैं इस लिंक का उपयोग करें और का उपयोग करके की जरूरत है मैं अपने सवाल – sunny

0

जोड़ें आपके संदर्भ के क्षेत्रों मैं कॉलम जो ON हिस्सा r.client_id, c.id

LEFT JOIN og_companies c ON r.client_id = c.id 
    LEFT JOIN og_rating_types t ON r.rating_type_id = t.id 
    LEFT JOIN og_actions a ON r.pacra_action = a.id 
    LEFT JOIN og_outlooks o ON r.pacra_outlook = o.id 
    LEFT JOIN og_lterms l ON r.pacra_lterm = l.id 
    LEFT JOIN og_sterms s ON r.pacra_sterm = s.id 
    LEFT JOIN pacra_client_opinion_relations pr ON pr.opinion_id = c.id 
    LEFT JOIN pacra_clients pc ON pc.id = pr.client_id 
    LEFT JOIN city ON city.id = pc.head_office_id 

की तरह में इतना कैसे आप एक सूचकांक mysql पर जोड़ सकते हैं मतलब करने के लिए सूचकांक?

एसक्यूएल >>ALTER TABLE your_table_name ADD INDEX (your_column_name);

भी बेहतर प्रदर्शन के लिए अपने में शामिल होने के कॉलम में समान संरचना होनी चाहिए। उदाहरण के लिए यदि आपका कॉलम_1 int (11) हस्ताक्षरित है तो दूसरी तरफ समान होना चाहिए।

  • कुछ आप सभी स्तंभों कि कर रहे हैं तालिका का हिस्सा मिलती
  • कुछ आप एक फिल्टर में इस्तेमाल किसी भी स्तंभ
  • स्पष्ट रूप से परिभाषित प्राथमिक कुंजी स्पष्ट रूप से विदेशी कुंजी रिश्तों
  • परिभाषित सूचक किया हुआ है पर अनुक्रमित किया हुआ है
  • बड़े डेटा सेट के लिए, उपयोग तालिका विभाजन नहीं NULL के रूप में जहां संभव
कॉलम परिभाषित करें

http://kb.tableau.com/articles/knowledgebase/database-query-performance

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