2012-12-08 11 views
8

2 प्रश्नों कि मुझे लगता है कि एक ही समारोह कर उपयोग कर सकते हैं बनाया है शामिल होता है। वे दोनों गुण होते हैं जिन्हें मैं एक ही क्वेरी में विलय करना चाहता हूं लेकिन मैं असमर्थ हूं।MySQL सूचकांक अनुकूलन

QUERY 1 - मुझे वही परिणाम देता है जो मैं चाहता हूं। धीरे (~ 0.700 सेकंड)

क्वेरी के 2 - मुझे पंक्तियों है कि मैं ध्यान न दें और छोड़ की एक बहुत कुछ देता है। फास्ट (~ 0.005 सेकंड)

मेरा लक्ष्य प्रत्येक आइटम के लिए 1 को छोड़कर सभी शून्य मूल्य पंक्तियों को छोड़ने के लिए QUERY 2 को संशोधित करना है। मैं प्रदर्शन पर एक डिंग लेने के साथ ऐसा नहीं कर सकता। यह MySQL में इंडेक्स उपयोग के अनुभव और समझ की कमी के कारण है।

क्वेरी के 1

एक खराब तरीके से तैयार सबक्वेरी जो भर में tbl_sale (ई) अनुक्रमण के उपयोग की अनुमति नहीं है जो 10k पंक्तियां हैं उपयोग करता है।

SELECT b.id, b.sv, b.description, der.store_id, f.name, der.price 
FROM tbl_watch AS a 
    LEFT JOIN tbl_item AS b ON a.item_id = b.id 
LEFT JOIN (
    SELECT c.store_id, d.flyer_id, e.item_id, e.price 
    FROM tbl_storewatch AS c, tbl_storeflyer AS d 
    FORCE INDEX (storebeg_ndx) , tbl_sale AS e 
    WHERE c.user_id = '$user_id' 
    AND (
     d.store_id = c.store_id 
     AND d.date_beg = '20121206' 
     ) 
    AND e.flyer_id = d.flyer_id 
     ) AS der ON a.item_id = der.item_id 
LEFT JOIN tbl_store as f ON der.store_id = f.id 
WHERE a.user_id = '$user_id' 
ORDER BY b.description ASC 

क्वेरी यहां 1

id select_type table  type possible_keys key    key_len  ref  rows Extra 
1 PRIMARY  a   ref  user_item_ndx user_item_ndx 4   const 30 Using index; Using temporary; Using filesort 
1 PRIMARY  b   eq_ref PRIMARY   PRIMARY   4   a.item_id 1 
1 PRIMARY  <derived2> ALL  NULL   NULL   NULL  NULL 300  
1 PRIMARY  f   eq_ref PRIMARY   PRIMARY   4   der.store_id 1 
2 DERIVED  c   ref  user_ndx  user_ndx  4     6 
2 DERIVED  e   ALL  NULL   NULL NULL NULL    9473 Using join buffer 
2 DERIVED  d   eq_ref storebeg_ndx storebeg_ndx 8   c.store_id 1 Using where 

क्वेरी के 2

के लिए व्याख्या है (आदेश द्वारा को छोड़कर) का उपयोग करता है सब छोड़ दिया मिलती है जो बहुत ही कुशल है। प्रत्येक शामिल होने पर इंडेक्स का उपयोग किया जाता है। यह क्वेरी tbl_watch में प्रत्येक आइटम के लिए सभी संभावित मिलान देता है।

id select_type  table type possible_keys   key    key_len  ref      rows Extra 
1 SIMPLE   a  ref  user_item_ndx   user_item_ndx 4   const     6  Using index; Using temporary; Using filesort 
1 SIMPLE   b  eq_ref PRIMARY     PRIMARY   4   a.item_id    1 
1 SIMPLE   c  ref  user_ndx    user_ndx  4   const     2 
1 SIMPLE   d  eq_ref storebeg_ndx,storendx storebeg_ndx 8   c.store_id,const  1 
1 SIMPLE   e  eq_ref itemflyer_ndx   itemflyer_ndx 8   a.item_id,d.flyer_id 1 
1 SIMPLE   f  eq_ref PRIMARY     PRIMARY   4   d.store_id    1 

मैंने QUERY 2 (अधिक कुशल) मेरे बस पंक्तियों मैंने QUERY 1 में करने के लिए की तरह की जरूरत है देने के लिए संशोधित कर सकते हैं कैसे:

SELECT b.id, b.sv, b.description, c.store_id, f.name, e.price 
FROM tbl_watch AS a 
LEFT JOIN tbl_item AS b ON a.item_id = b.id 
LEFT JOIN tbl_storewatch AS c ON c.user_id = '$user_id' 
LEFT JOIN tbl_storeflyer AS d ON d.store_id = c.store_id 
    AND d.date_beg = '$s_date' 
LEFT JOIN tbl_sale AS e ON e.item_id = a.item_id 
    AND e.flyer_id = d.flyer_id 
LEFT JOIN tbl_store as f ON d.store_id = f.id 
WHERE a.user_id = '$user_id' 
ORDER BY b.description ASC 

क्वेरी के लिए व्याख्या है: क्वेरी है के साथ काम?

धन्यवाद माइक

+0

मुझे सच में यकीन नहीं है कि यह कैसे संभव है कि पहली क्वेरी आपको वह चाहिए जो आप चाहते हैं। एक बाएं जॉइन बाएं बाहरी जुड़ाव नहीं है (हालांकि शायद यह MySQL में है, यह गैर-एसक्यूएल अनुपालन है), और नल अद्वितीय मान नहीं हैं। मेरे पास MySQL आसान नहीं है, लेकिन PostgreSQL में इसे छोड़ना आपके द्वारा वर्णित परिणामों को नहीं देता है। मेरा जवाब नीचे ... – PlexQ

उत्तर

0

आपका सबसिलेक्ट QUERY में 1 अंतर्निहित आंतरिक उपयोग कर रहा है, मिलती है, जबकि क्वेरी 2 उपयोग कर रहा है सब छोड़ दिया मिलती स्पष्ट मिलती है।

SELECT b.id, b.sv, b.description, c.store_id, f.name, e.price 
FROM tbl_watch AS a 
LEFT JOIN tbl_item AS b ON a.item_id = b.id 
LEFT JOIN tbl_storewatch AS c ON c.user_id = '$user_id' 
-- Left removed below 
JOIN tbl_storeflyer AS d ON d.store_id = c.store_id 
    AND d.date_beg = '$s_date' 
-- Left removed below 
JOIN tbl_sale AS e ON e.item_id = a.item_id 
    AND e.flyer_id = d.flyer_id 
LEFT JOIN tbl_store as f ON d.store_id = f.id 
WHERE a.user_id = '$user_id' 
ORDER BY b.description ASC` 

तुम भी लेने पर विचार हो सकता है: इस प्रकार, क्वेरी 2 में डेटा बहिष्कृत करने मैं लाइनों के एक जोड़े में छोड़ दिया है बाहर ले जाना चाहते हैं (के रूप में चिह्नित) और देखते हैं कि यह कैसे चीजें बेहतर बनाता है कोई जहां खंड हैं और जुड़ जाता है और उन्हें कहां में जाने से बाहर खंड:

SELECT b.id, b.sv, b.description, c.store_id, f.name, e.price 
FROM tbl_watch AS a 
LEFT JOIN tbl_item AS b ON a.item_id = b.id 
LEFT JOIN tbl_storewatch AS c ON c.user_id = '$user_id' 
JOIN tbl_storeflyer AS d ON d.store_id = c.store_id 
JOIN tbl_sale AS e ON e.item_id = a.item_id 
LEFT JOIN tbl_store as f ON d.store_id = f.id 
WHERE a.user_id = '$user_id' 
AND d.date_beg = '$s_date' 
AND e.flyer_id = d.flyer_id 
ORDER BY b.description ASC 

और अंत में, तिथि गणित काफी गहन है। क्वेरी 2 में, बाहरी जॉइन का उपयोग करके, आप इससे बहुत से बचते हैं, लेकिन आपको इसकी आवश्यकता हो सकती है। मुझे लगता है कि द्वारा आईडी प्राप्त करने के लिए एक सबक्वेरी का उपयोग करें और प्रतिबंधित करने के लिए कोशिश करेंगे:

SELECT b.id, b.sv, b.description, c.store_id, f.name, e.price 
FROM tbl_watch AS a 
LEFT JOIN tbl_item AS b ON a.item_id = b.id 
LEFT JOIN tbl_storewatch AS c ON c.user_id = '$user_id' 
JOIN tbl_storeflyer AS d ON d.store_id = c.store_id 
JOIN tbl_sale AS e ON e.item_id = a.item_id 
LEFT JOIN tbl_store as f ON d.store_id = f.id 
WHERE a.user_id = '$user_id' 
AND e.flyer_id = d.flyer_id 
AND d.id in (select d.id from d where date_beg = '$s_date') 
ORDER BY b.description ASC 
+0

आपकी प्रतिक्रिया के लिए धन्यवाद! ये समाधान सक्रिय बिक्री वस्तुओं (e.item_id = a.item_id और e.flyer_id = d.flyer_id) वाले सभी आइटमों के लिए पंक्तियां देते हैं, लेकिन मैं प्रत्येक आइटम को tbl_watch (ए) में (बी) फ़ील्ड के साथ भी शामिल करने का प्रयास कर रहा था, भले ही वे tbl_sale (ई) में मौजूद नहीं हैं। तो मैं इसके साथ समाप्त होगा: आईडी, एसवी, विवरण, नल, पूर्ण, पूर्ण। मैं केवल 1 पंक्ति को प्रति आइटम NULL के साथ अनुमति देना चाहता था। मुझे यकीन नहीं है कि इसे कैसे पूरा किया जाए। – ridgeback

+0

बस स्पष्ट करने के लिए मैं प्रत्येक आइटम को 3 परिदृश्यों में से 1 में गिरने की उम्मीद करता हूं: 1 - एकल मूल्य वाला आइटम। 2 - कई कीमतों के साथ आइटम। 3 - कीमतों के साथ आइटम। यदि 3 होता है तो भी मैं आइटम आईडी, एसवी और विवरण के साथ एक पंक्ति लौटाता हूं। – ridgeback

+0

यह सुनिश्चित नहीं है कि date_beg यहां एक वास्तविक दिनांक फ़ील्ड है, ऐसा लगता है कि इसे किसी प्रकार के char के रूप में उपयोग किया जा रहा है। मुझे यकीन नहीं है कि MySQL में डेट मैच धीमा हो रहा है, लेकिन मुझे आश्चर्य होगा। तिथियां आम तौर पर लंबे समय तक आंतरिक रूप से संग्रहीत होती हैं, और केवल एक ही लागत उस स्ट्रिंग को लंबे समय तक घुमाने के लिए होती है, इसलिए मुझे विश्वास नहीं है कि यह किसी भी ओवरहेड को जोड़ देगा। – PlexQ

1

मुझे लगता है कि इस क्वेरी आप दे देंगे आप क्या चाहते हैं:

select a.id, a.sv, a.description, c.id, c.name, b.price 
    from 
    tbl_item a left outer join tbl_sale b on (a.id=b.item_id) 
     left outer join tbl_storeflyer d on (b.flyer_id=d.flyer_id and d.date_beg = '20120801') 
     left outer join tbl_store c on (d.store_id = c.id) 
     left outer join tbl_storewatch x on (c.id = x.store_id) 
     left outer join tbl_watch y on (a.id = y.item_id); 
शामिल NULLs साथ

, आप की संभावना जा रहे हैं कुछ बाएं जुड़ने के लिए।- पर कैसे निर्भर करता है

select a.id, a.sv, a.description, c.id as store_id, c.name, b.price 
    from 
    tbl_item a, 
    tbl_sale b, 
    tbl_storeflyer d, 
    tbl_store c, 
    tbl_storewatch x, 
    tbl_watch y 
    where 
    a.id = b.item_id and 
    b.flyer_id = d.flyer_id and 
    d.store_id = c.id and 
    c.id = x.store_id and 
    a.id = y.item_id and 
    d.date_beg = '20120801' 
union 
select a.id, a.sv, a.description, null as store_id, null as name, null as price 
    from 
    tbl_item a 
    where 
    a.id not in (select b.item_id from tbl_sale b); 

आप संघ एक छोड़ दिया बाहरी जा रहा है की दूसरी छमाही के साथ खेलने के बजाय एक सबक्वेरी 'नहीं' में शामिल होने: वैकल्पिक तरीका एक संघ है, जो MySQL ज़्यादा तेज़ हो सकता उपयोग करने के लिए है MySQL का आपका संस्करण अनुकूलित करता है।

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