2017-07-28 11 views
6

मेरे पास दो टेबल हैं। order_details जो 100,000 पंक्तियां हैं, और outbound जो 10,000 पंक्तियां हैं।यह सरल पूछताछ क्वेरी उप-क्वेरी के साथ काफी तेज क्यों है?

मुझे order_number नामक कॉलम पर उनसे जुड़ने की आवश्यकता है, जो दोनों पर एक वर्चर (50) है। आउटबाउंड तालिका में order_number अद्वितीय नहीं है।

CREATE TABLE `outbound` (
    `outbound_id` int(12) NOT NULL, 
    `order_number` varchar(50) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

CREATE TABLE `order_details` (
    `order_details_id` int(12) NOT NULL, 
    `order_number` varchar(50) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

यह मेरा प्रारंभिक क्वेरी है, और इसे चलाने के लिए अच्छी तरह से 60 से अधिक सेकंड लेता है:

SELECT o.order_number 
FROM outbound o 
INNER JOIN order_details od 
    ON o.order_number = od.order_number 

इस क्वेरी एक ही परिणाम हो जाता है और चलाने के लिए एक सेकंड से भी कम समय लगता है:

SELECT o.order_number 
FROM outbound o 
INNER JOIN 
(
    SELECT order_number 
    FROM order_details 
) od 
ON (o.order_number = od.order_number) 

यह मेरे लिए आश्चर्यजनक है क्योंकि आमतौर पर उप-प्रश्न काफी धीमे होते हैं।

रनिंग EXPLAIN (जो मैं अभी भी कैसे को समझने के लिए सीख रहा हूँ) से पता चलता उप क्वेरी संस्करण एक derived2 तालिका का उपयोग करता है, कि यह एक सूचकांक उपयोग कर रहा है, और कहा कि सूचकांक auto_key0 है। मैं समझने के लिए पर्याप्त समझ में नहीं आता कि यह समझने के लिए कि यह क्यों महत्वपूर्ण अंतर बनाता है।

मैं कमांड लाइन पर इन प्रश्नों को चला रहा हूं।

मैं लिनक्स (x86_64) CentOS के लिए MySQL Ver 14.14 Distrib 5.6.35 चला रहा हूं।

सारांश में:

क्यों इस सरल एक उप क्वेरी के साथ काफी तेज क्वेरी में शामिल होने की जाती है?

+0

MySQL का खराब अनुकूलक? क्या आपने 'EXISTS' या 'IN' के साथ भी तुलना की थी? 'आउटबाउंड से o.order_number चयन ओ कहां मौजूद है' या 'o.order_number चयन आउटबाउंड से ओ ( आयुध डिपो के रूप में ORDER_DETAILS कहां o.order_number = od.order_number से ORDER_NUMBER का चयन करें) कहां ( का चयन करें ORDER_NUMBER order_number आदेश_details से) ' – dnoeth

+0

@ डेनोथ कि पहली क्वेरी एक मिनट से अधिक समय लेती है, कि दूसरी क्वेरी तत्काल है। – Goose

+1

जैसा कि मैंने कहा था, एक सभ्य अनुकूलक को सभी चार समानों का इलाज करना चाहिए (वास्तव में जब join'd_details.orde_number' अद्वितीय नहीं होता है तो वास्तव में जुड़ने का एक अलग परिणाम मिल सकता है)। – dnoeth

उत्तर

5

MySQL का मेरा ज्ञान बहुत सीमित है। लेकिन ये मेरे विचार हैं:

आपकी तालिकाओं में अनुक्रमणिका नहीं है। फिर पहली तालिका की प्रत्येक पंक्ति के लिए, तुलना करने के लिए जुड़ने के लिए पूरी दूसरी तालिका को पढ़ना होगा।

सबक्वायरी एक बार दूसरी तालिका पढ़ता है और एक अनुक्रमणिका बनाता है, तो उसे पहली तालिका की प्रत्येक पंक्ति के लिए पूरी दूसरी तालिका को पढ़ने की आवश्यकता नहीं है। इसे केवल इंडेक्स की जांच करनी है, जो बहुत तेज है।

यह सत्यापित करने के लिए कि मैं रिटघट हूं या नहीं, अपने दो टेबलों में कॉलम order_number के लिए इंडेक्स बनाने का प्रयास करें (INDEX बनाएं ...), और फिर दो प्रश्नों को चलाएं। आपकी पहली क्वेरी केवल एक मिनट के बजाय एक सेकंड से कम लेनी चाहिए।

+0

इस परीक्षण के लिए डेटा को मेरे देव को खींचने का दर्द था, लेकिन जब मैंने पाया कि आपका उत्तर सटीक है। उत्तर के लिए धन्यवाद, समझ में आता है। – Goose

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