2010-08-05 15 views
12

अद्यतन करने के लिए 180 सेकंड लगते हैं अद्यतन:इस चयन क्वेरी को

बस इसे और अधिक दृश्यमान स्थान पर उल्लेख करने के लिए। जब मैंने IN के लिए IN बदल दिया, तो क्वेरी निष्पादन समय 180 से घटाकर 0.00008 सेकेंड तक चला गया। हास्यास्पद गति अंतर।


यह SQL क्वेरी समाप्त करने के लिए 180 सेकंड लगती है! वो कैसे संभव है? क्या इसे तेजी से अनुकूलित करने का कोई तरीका है?

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion IN 
    (
    SELECT MAX(IdQuestionLawVersion) 
    FROM question_law_version 
    WHERE IdQuestionLaw IN 
    (
    SELECT MIN(IdQuestionLaw) 
    FROM question_law 
    WHERE IdQuestion=236 AND IdQuestionLaw>63 
    ) 
) 

प्रत्येक तालिका में केवल 5000 पंक्तियां हैं इसलिए यह इतनी धीमी नहीं होनी चाहिए। अच्छी तरह से अनुक्रमित (यदि सभी) का उपयोग नहीं कर -

+5

यदि आप करने के लिए '' '= IN' बदल कोई अंतर है? –

+7

उन कॉलम नामों ने मेरे दिमाग को चोट पहुंचाई। क्या आप समझा सकते हैं कि क्वेरी क्या करना है? – RedFilter

+0

@ मार्टिन स्मिथ यह आश्चर्यजनक होगा (और मेरे लिए शैक्षणिक) यदि इससे कोई फर्क पड़ता है। –

उत्तर

16

कोई फर्क अगर आप IN बदल = पर?

यदि कोई इस की जांच करना चाहता है तो मैंने अभी परीक्षण किया है और इसे पुन: पेश करना बहुत आसान पाया है।

तालिका बनाएं

CREATE TABLE `filler` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`) 
) 

प्रक्रिया

CREATE PROCEDURE `prc_filler`(cnt INT) 
BEGIN 
     DECLARE _cnt INT; 
     SET _cnt = 1; 
     WHILE _cnt <= cnt DO 
       INSERT 
       INTO filler 
       SELECT _cnt; 
       SET _cnt = _cnt + 1; 
     END WHILE; 
END 

आबाद टेबल

call prc_filler(5000) 

क्वेरी 1

SELECT id 
FROM filler 
WHERE id = (SELECT MAX(id) FROM filler WHERE id = 
(SELECT MIN(id) 
    FROM filler 
    WHERE id between 2000 and 3000 
    ) 
) 
बनाएं

Equals Explain Output http://img689.imageshack.us/img689/5592/equals.png

क्वेरी 2 (एक ही समस्या)

SELECT id 
FROM filler 
WHERE id in (SELECT MAX(id) FROM filler WHERE id in 
(SELECT MIN(id) 
    FROM filler 
    WHERE id between 2000 and 3000 
    ) 
) 

In Explain Output http://img291.imageshack.us/img291/8129/52037513.png

+0

मैं कुछ MySQL विशेषज्ञों के प्रदर्शन में अंतर पर टिप्पणी करने के लिए उत्सुक हूं। जाहिर है कि उपक्विरी केवल 1 पंक्ति वापस करने जा रही हैं, इसलिए बराबर सही ऑपरेटर है, लेकिन इन्हें इतना बड़ा प्रदर्शन अंतर क्यों बनायेगा जब यह केवल जांच कर रहा है कि मान 1-पंक्ति परिणाम में पाया जाता है या नहीं? – wadesworld

+3

@Wade - मार्क का जवाब यहां कवर किया गया है मुझे लगता है कि http://stackoverflow.com/questions/3417074/why-would-an-in-condition-be-slower-than-in-sql/3417190#3417190 –

12

Here is a good explanation why = is better than IN

Mysql भीतरी प्रश्नों के साथ समस्या है।

  1. सुनिश्चित करें कि आप में शामिल होने के/में सभी क्षेत्रों पर अनुक्रमित है जहां/आदेश आदि
  2. प्राप्त एक अलग क्वेरी में उन लोगों के मैक्स और मिन मूल्यों (उपयोग इस पूरे बात के लिए प्रक्रिया संग्रहीत अगर आप छोड़ना चाहते हैं एक से अधिक अनुरोध भूमि के ऊपर या बस वैसे भी कई प्रश्न के साथ एक अनुरोध करना

:।

SELECT 
     IdLawVersionValidFrom 
FROM 
     question_law_version 
    JOIN 
     question_law 
     ON 
     question_law_version.IdQuestionLaw = question_law.IdQuestionLaw 
WHERE 
     question_law.IdQuestion=236 
    AND 
     question_law.IdQuestionLaw>63 

ORDER BY 
     IdQuestionLawVersion DESC, 
     question_law.IdQuestionLaw ASC 
LIMIT 1 
+0

+1 मेरा मतलब इंडेक्स का उल्लेख करना था, लेकिन ... किसी भी तरह ... नहीं किया :) – Unreason

+0

वास्तव में मार्टिन स्मिथ की टिप्पणी सही जवाब है। –

+0

@ रिचर्ड नॉप - क्या मेरी क्वेरी आपके लिए काम करती है या नहीं? –

4

आप EXPLAIN उपयोग कर सकते हैं पता लगाने के लिए एक के लिए यह संभव है इतनी धीमी गति से निष्पादित करने के लिए क्वेरी।

MySQL वास्तव में नेस्टेड उप-चयन पसंद नहीं करता है, तो संभवतः यह होता है कि यह होता है और यह न्यूनतम और अधिकतम पाने के लिए डिस्क पर चलता है और परिणामों का पुन: उपयोग करने में विफल रहता है।

जुड़ने के रूप में पुनर्लेखन शायद इसकी मदद करेगा।

बस एक त्वरित फिक्स कोशिश की तलाश में हैं: (! मेरी टिप्पणी पोस्ट जाहिरा तौर पर यह एक फर्क किया था एक जवाब के रूप)

SET @temp1 =  
    (
    SELECT MIN(IdQuestionLaw) 
    FROM question_law 
    WHERE IdQuestion = 236 AND IdQuestionLaw > 63 
) 

SET @temp2 = 
    (
    SELECT MAX(IdQuestionLawVersion) 
    FROM question_law_version 
    WHERE IdQuestionLaw = @temp1 
) 

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion = @temp2 
+0

दरअसल मार्टिन स्मिथ की टिप्पणी सही जवाब है। –

+0

पूरी तरह से सहमत हैं और उस पर +1 दिया है। 'EXPLAIN' के उपयोग का ध्यान दें :) – Unreason

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