2013-05-25 8 views
12

से 20 गुना धीमी है, मेरे पास टेबल नाम को छोड़कर एक ही संरचना के साथ 10 टेबल हैं।mysql संग्रहीत प्रक्रिया मानक क्वेरी

select * from table1 where (@param1 IS NULL OR [email protected]) 
UNION ALL 
select * from table2 where (@param1 IS NULL OR [email protected]) 
UNION ALL 
... 
... 
UNION ALL 
select * from table10 where (@param1 IS NULL OR [email protected]) 

मैं निम्न पंक्ति के साथ एसपी बोल रहा हूँ:

call mySP('test') //it executes in 6,836s 

तो मैं एक नया मानक क्वेरी विंडो खोली

मैं एक एसपी (संग्रहीत प्रक्रिया) निम्नलिखित के रूप में परिभाषित किया गया है। मैंने अभी उपरोक्त क्वेरी की प्रतिलिपि बनाई है। फिर 'param' के साथ @ param1 को बदल दिया।

यह 0,321s में निष्पादित और संग्रहीत प्रक्रिया से लगभग 20 गुना तेज है।

मैंने कैश किए जाने के परिणाम को रोकने के लिए बार-बार पैरामीटर मान बदल दिया। लेकिन इसने परिणाम नहीं बदला। एसपी समकक्ष मानक क्वेरी की तुलना में लगभग 20 गुना धीमी है।

क्या आप यह जानने में मेरी सहायता कर सकते हैं कि यह क्यों हो रहा है?

क्या किसी को भी इसी तरह के मुद्दों का सामना करना पड़ा?

मैं विंडोज सर्वर 2008 आर 2 64 बिट पर mySQL 5.0.51 का उपयोग कर रहा हूं।

संपादित करें: मैं परीक्षण के लिए Navicat का उपयोग कर रहा हूँ।

कोई भी विचार मेरे लिए सहायक होगा।

EDIT1:

मैं सिर्फ Barmar के जवाब के अनुसार कुछ परीक्षण किया है।

अंत में मैं एक सिर्फ एक पंक्ति के साथ नीचे की तरह एसपी को बदल दिया है:

SELECT * FROM table1 WHERE [email protected] AND [email protected] 

तो सबसे पहले मैं standart क्वेरी

SELECT * FROM table1 WHERE col1='test' AND col2='test' //Executed in 0.020s 

निष्पादित करने के बाद मैं अपने एसपी कहा जाता है:

CALL MySp('test','test') //Executed in 0.466s 

तो मैंने पूरी तरह से खंड बदल दिया है लेकिन कुछ भी नहीं बदला है। और मैंने नेविचैट की बजाय mysql कमांड विंडो से sp को बुलाया। यह एक ही परिणाम दिया। मैं अभी भी इस पर अटक गया हूँ।

मेरी एसपी DDL:

CREATE DEFINER = `myDbName`@`%` 
PROCEDURE `MySP` (param1 VARCHAR(100), param2 VARCHAR(100)) 
BEGIN 
    SELECT * FROM table1 WHERE col1=param1 AND col2=param2 
END 

और col1 और col2 अनुक्रमित संयुक्त है।

आप कह सकते हैं कि आप स्टैंड स्टैंड क्वेरी का उपयोग क्यों नहीं करते? मेरा सॉफ़्टवेयर डिज़ाइन इसके लिए उचित नहीं है। मुझे संग्रहीत प्रक्रिया का उपयोग करना होगा। तो यह समस्या मेरे लिए बेहद महत्वपूर्ण है।

EDIT2:

मैं मिल गया है क्वेरी प्रोफ़ाइल जानकारियां। एसपी प्रोफाइल जानकारी में "डेटा पंक्ति भेजने" के कारण बड़ा अंतर है। डेटा भाग भेजना क्वेरी निष्पादन समय के% 99 लेता है। मैं स्थानीय डेटाबेस सर्वर पर परीक्षण कर रहा हूं। मैं रिमोट कंप्यूटर से कनेक्ट नहीं कर रहा हूँ।

सपा प्रोफ़ाइल जानकारी SP Profile Information

क्वेरी प्रोफ़ाइल जानकारी enter image description here

मैं अपने एसपी में नीचे की तरह बल सूचकांक बयान कोशिश की है। लेकिन एक ही परिणाम।

SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE [email protected] AND [email protected] 

मैंने नीचे की तरह sp को बदल दिया है।

id:1 
select_type=SIMPLE 
table:table1 
type=ref 
possible_keys:NULL 
key:NULL 
key_len:NULL 
ref:NULL 
rows:292004 
Extra:Using where 

तब मैं नीचे दिए गए क्वेरी निष्पादित:

EXPLAIN SELECT * FROM table1 FORCE INDEX (col1_col2_combined_index) WHERE col1=param1 AND col2=param2 

यह इस परिणाम दे दी है।

EXPLAIN SELECT * FROM table1 WHERE col1='test' AND col2='test' 

परिणाम है:

id:1 
select_type=SIMPLE 
table:table1 
type=ref 
possible_keys:col1_co2_combined_index 
key:col1_co2_combined_index 
key_len:76 
ref:const,const 
rows:292004 
Extra:Using where 

मैं सपा में बल सूचकांक कथन का उपयोग कर रहा हूँ। लेकिन यह सूचकांक का उपयोग नहीं करने पर जोर देता है। कोई उपाय? मुझे लगता है कि मैं पास हूँ समाप्त करने के लिए :)

+1

यह हो सकता है कि एसपी को निष्पादित करने के बाद, MySQL ने परिणाम कैश किया है, और फिर जब आप इसे एसपी के बाहर निष्पादित करते हैं, तो यह फिर से इसे निष्पादित करने के बजाय कैश को मार रहा है। –

+0

वैसे, एक ही संरचना के साथ 10 टेबल क्यों? उन्हें 1 टेबल में क्यों न मिलाएं? –

+0

डेटाबेस डिज़ाइन मेरे हाथ से बाहर है मैं कभी ऐसा डिज़ाइन नहीं करूंगा :) पहले मैं अलग पैरामीटर के साथ क्वेरी निष्पादित करता हूं, फिर तुरंत मैं उसी पैरामीटर के साथ स्पैम को कॉल करता हूं। नतीजा ऐसा लगता है कि एसपी ने भी कैश से परिणाम नहीं लिया। – bselvan

उत्तर

4

संभावित चरित्र सेट मुद्दा? यदि आपका टेबल कैरेक्टर सेट आपके डेटाबेस कैरेक्टर सेट से अलग है, तो इससे समस्या हो सकती है। http://bugs.mysql.com/bug.php?id=26224

[12 नवंबर 2007 21:32] मार्क Kubacki फिर भी कोई 5.1 के साथ भाग्य:

इस बग रिपोर्ट देखें।22_rc - कुंजी शामिल हैं, क्वेरी 36 सेकंड की प्रक्रिया में और 0.12s के बाहर ले जाती है।

[12 नवंबर 2007 22:30] मार्क Kubacki UTF-8 में बदल गए वर्णसेट होने (दो इस्तेमाल किया विशेष रूप से के लिए) है, जो वैसे भी कनेक्शन के लिए प्रयोग किया जाता है के बाद, कुंजी संग्रहीत प्रक्रिया के भीतर ध्यान में रखा जाता!

जिस प्रश्न का मैं उत्तर नहीं दे सकता हूं वह है: ऑप्टिमाइज़र कैरेट रूपांतरण प्रक्रियाओं के भीतर और बाहर किसी अन्य तरीके से क्यों व्यवहार करता है? (वास्तव में, मैं गलत यह पूछ हो सकता है।)

+0

आपको बहुत बहुत धन्यवाद। कारण बिल्कुल वही है। मेरी टेबल और डेटाबेस चरित्र सेट अलग था। मैंने दोनों को एक ही बदल दिया है, फिर सूचकांक एसपी में इस्तेमाल किया गया है। – bselvan

8

बस एक अनुमान:

जब आप हाथ से क्वेरी, अभिव्यक्ति जब क्वेरी पार्स किया जा रहा है WHERE ('test' IS NULL or COL1 = 'test') अनुकूलित किया जा सकता है चलाते हैं। पार्सर देख सकता है कि स्ट्रिंग 'test' शून्य नहीं है, इसलिए यह परीक्षण को WHERE COL1 = 'test' में परिवर्तित करता है। और यदि COL1 पर कोई अनुक्रमणिका है तो इसका उपयोग किया जाएगा।

हालांकि, जब आप एक संग्रहीत प्रक्रिया बनाते हैं, प्रक्रिया तब बनाई जाती है जब प्रक्रिया बनाई जाती है। उस समय, यह नहीं पता कि @param क्या होगा, और तालिका को अनुक्रमिक स्कैन के रूप में क्वेरी को कार्यान्वित करना होगा।

करने के लिए अपने प्रक्रिया को बदलने का प्रयास करें:

IF @param IS NULL 
THEN BEGIN 
    SELECT * FROM table1 
    UNION ALL 
    SELECT * FROM table2 
    ... 
END; 
ELSE BEGIN 
    SELECT * FROM table1 WHERE col1 = @param 
    UNION ALL 
    SELECT * FROM table2 WHERE col1 = @param 
    ... 
END; 
END IF; 

मैं MySQL संग्रहित प्रक्रियाओं का अधिक अनुभव नहीं है, इसलिए मुझे यकीन है कि सब ठीक वाक्य रचना है नहीं कर रहा हूँ।

+0

उत्तर के लिए धन्यवाद। मैं कोशिश करूंगा। असल में मेरा जहां खंड इतना छोटा नहीं है। (@ param1 शून्य या col1 = @ param1 है) और (@ param2 null या col2 = @ param2 है) और .... param6 पर। स्पष्ट होने के लिए, मैंने इतना विस्तृत लिखा नहीं है। क्षमा करें। मुझे लगता है कि इस साइट पर आपका समाधान बिल्कुल मेरे प्रश्न को कवर नहीं करता है। – bselvan

+0

अंतर भिन्नता का उपयोग करने से आता है क्योंकि '@Var शून्य या col1 = @ var' है। दोनों पर एक्सप्लाइन चलाएं: 'मेरा चयन करें * से चुनें * और 'SPLECTY से SP_MY_PROC' चुनें। यह कारण क्यों देना चाहिए। SQL सर्वर में निष्पादन योजना को पुन: संकलित करने के लिए ऐसे मामलों में उपयोग करने के लिए विकल्प और विकल्प रिकॉम्पली है। मैं देख रहा हूं लेकिन MySQL में ऐसा कुछ नहीं ढूंढ रहा हूं। – Stoleg

+0

@Stoleg यह मेरा मूल स्पष्टीकरण था, लेकिन वह अपने नवीनतम संस्करण में 'OR' से छुटकारा पा लिया। इसलिए मुझे नहीं पता कि एसपी अभी भी धीमा क्यों होगा। – Barmar

0

दिलचस्प सवाल, क्योंकि मैं संग्रहित प्रक्रियाओं का उपयोग करने का शौक हूं। कारण रखरखाव और encapsulation सिद्धांत है।

यह मैंने पाया जानकारी है: http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html

यह कहा गया है कि क्वेरी कैश प्रश्नों के लिए इस्तेमाल नहीं किया है कि 1. एक सबक्वेरी कि एक बाहरी क्वेरी से संबंधित हैं, और 2. शरीर के भीतर क्रियान्वित कर रहे हैं एक संग्रहीत प्रक्रिया, ट्रिगर या घटना के।

इसका तात्पर्य है कि यह डिज़ाइन के रूप में कार्य करता है।

0

मैं इस व्यवहार को देखा था, लेकिन यह वर्ण सेट से संबंधित नहीं था।

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

जब मैं एक विशेष माता-पिता के सभी बच्चों (सभी स्तरों पर) खोजने के लिए रिकर्सिव क्वेरी करने के लिए संग्रहीत प्रक्रिया चलाने के लिए चला गया, तो क्वेरी 30 चलाने के लिए 40 गुना के बीच ले गई। मैंने पाया कि संग्रहित प्रक्रिया द्वारा उपयोग की गई क्वेरी को बदलने के लिए यह सुनिश्चित करने के लिए कि यह शीर्ष-स्तरीय अभिभावक रिकॉर्ड को बहिष्कृत करता है (WHERE parent_id! = Id निर्दिष्ट करके) क्वेरी के प्रदर्शन को पुनर्स्थापित कर दिया गया है।

संग्रहीत प्रक्रिया जो मैं उपयोग कर रहा हूं वह उस पर आधारित है: https://stackoverflow.com/questions/27013093/recursive-query-emulation-in-mysql

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