2008-12-04 6 views
8

मैं {लोअरकेस "एक" के साथ शुरू नाम के साथ ग्राहकों} के सभी कर्मचारियों को पाने के लिए इस क्वेरी का उपयोग कर रहा में:MySQL - कैसे सूचकांक का उपयोग करने के जहां एक्स में (<subquery>)

SELECT * FROM employees 
    WHERE client_id IN (SELECT id FROM clients WHERE name LIKE 'a%') 

कॉलम employees.client_id एक है int, INDEX client_id (index_id) के साथ। सबक्वायरी को IMHO आईडी-एस की एक सूची वापस करनी चाहिए, जिसका उपयोग WHERE क्लॉज में किया जाता है।

जब मैं EXPLAIN क्वेरी करता हूं, तो प्राथमिक क्वेरी कोई अनुक्रमणिका (type:ALL) का उपयोग नहीं करती है। लेकिन जब मैं EXPLAIN सबक्वायरी (उदा। SELECT ... WHERE client_id IN (121,184,501)) से ली गई एक सूची, EXPLAINtype:range पर स्विच करता है, और यह क्वेरी 50% तक तेज़ी से हो जाती है।

मैं क्वेरी को सबक्वायरी द्वारा लौटाए गए डेटा के लिए इंडेक्स का उपयोग कैसे कर सकता हूं - या, क्या इस डेटा को पुनर्प्राप्त करने का एक और अधिक प्रभावी तरीका है? (एप्लिकेशन सर्वर पर आईडी-सूची पुनर्प्राप्त करना, इसमें शामिल होना और दूसरी क्वेरी भेजना यहां और भी महंगा है)।

अग्रिम धन्यवाद।

उत्तर

12
SELECT employees.* 
FROM employees, clients 
WHERE employees.client_id = clients.id 
AND clients.name LIKE 'a%'; 

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

के रूप में एक सामान्य नियम के उप प्रश्नों से बचा जाना चाहिए, क्योंकि वे आम तौर पर कम performant से एक प्रश्न में शामिल होने के लिए किया जाएगा (कुछ विशेष परिस्थितियों जहां वे अपरिहार्य हैं देखते हैं, हालांकि)

+0

इनर जॉइन सिंटैक्स का भी उपयोग कर सकता है। – MarkR

+0

मैंने ऐसे मामलों को देखा है जहां क्वेरी ऑप्टिमाइज़र वास्तव में गलत हो जाता है, और आईडी को वापस करने के लिए एक सबक्वायरी तेज़ी से लोड हो जाती है। लेकिन यह वास्तव में एक विशिष्ट मामला था। देखें: http://www.benlumley.co.uk/2008/06/25/mysql-query-optimiser-left-lacking/ यदि आप विवरण में रूचि रखते हैं। – benlumley

5

आप एक JOIN के साथ ऐसा करने की कोशिश की है और एक subselecct नहीं है?

SELECT employees.* FROM employees, clients WHERE employees.client_id = clients.id AND clients.name LIKE 'a%'; 
2

यह उनका कहना है कि सबक्वेरी से बेहतर प्रदर्शन कर हर डीबीएमएस है के लिए सच नहीं होता है मिलती है लायक है। यह निश्चित रूप से MySQL के लिए करता है।

0
select * from X as _x where 
    exists(select * from Y as _y where _y.someField = _x.someField) 

आप के लिए चाल करना चाहिए;)

1
SELECT e.* 
FROM employees e 
WHERE EXISTS ( 
    SELECT 1  
    FROM clients c 
    WHERE c.id = e.client_id 
    AND c.name LIKE 'a%' 
) 

आप का उपयोग मौजूद क्वेरी पुनर्लेखन कर सकते हैं। MySQL में, यह निश्चित रूप से एक प्रदर्शन सुधार देता है। अधिक अनुकूलन सहायता के लिए, आप उल्लेख कर सकते: MySQL-In-Query-Optimization

+0

मुझे नहीं लगता कि किसी भी प्रकार की सबक्वायरी का उपयोग MySQL के साथ एक सुधार है। – mat

4

क्यों

SELECT * FROM employees WHERE client_id IN (SELECT id FROM clients WHERE name LIKE 'a%') 

MySQL मैनुअल के इस हिस्से बाहर धीमी गति से

SELECT * FROM employees WHERE client_id IN (1,2,3,4) 

चेक, particuarly तीसरा डॉट है पर एक विशेष विवरण के लिए बिंदु: http://dev.mysql.com/doc/refman/5.0/en/subquery-restrictions.html। इसके अलावा, यह bug report