2013-10-09 10 views
9

मैं आगे की प्रक्रिया के लिए एक अस्थायी तालिका में एक क्वेरी परिणाम स्टोर करने की कोशिश कर रहा हूं।MySQL 'क्यों डालें ... चुनें ...' अकेले चयन से बहुत धीमा है?

create temporary table tmpTest 
(
    a FLOAT, 
    b FLOAT, 
    c FLOAT 
) 
engine = memory; 

insert into tmpTest 
(
    select a,b,c from someTable 
    where ... 
); 

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

अद्यतन मेरे सेटअप: MySQL 8 डेबियन लिनक्स NDB डेटा नोड्स 1 एसक्यूएल नोड (विंडोज सर्वर 2012)

तालिका मैं पर चुनिंदा चल रहा हूँ के साथ 7.3.2 क्लस्टर एक NDB है तालिका।

मैं, जानने की कोशिश करता है, तो का उपयोग करते समय कार्य योजना लागू करके अलग होता है 'में सम्मिलित ..', लेकिन वे एक ही लग रही है: (स्वरूपण के लिए खेद है, stackoverflow नहीं है टेबल्स)

 
id select_type  table  type possible_keys key  key_len ref     rows  Extra 
1 PRIMARY   <subquery3> ALL  \N    \N  \N  \N     \N   \N 
1 PRIMARY   foo   ref  PRIMARY   PRIMARY 3  <subquery3>.fooId 9747434  Using where 
2 SUBQUERY  someTable range PRIMARY   PRIMARY 3  \N     136933000 Using where with pushed condition; Using MRR; Using temporary; Using filesort 
3 MATERIALIZED tmpBar  ALL  \N    \N  \N  \N     1000  \N 

तालिका बनाएं ... चयन भी धीमा है। बिना टेबल डालने/बनाने के 47 सेकंड बनाम 5 सेकंड।

+1

आपको अधिक विशिष्ट होना चाहिए और कुछ डेटा जो आप लिख रहे हैं उसे प्रदान करना चाहिए। इसके अलावा 'INSERT .. चयन करें' वाक्यविन्यास अलग है। आपके नमूने के परिणामस्वरूप त्रुटि होगी। –

+0

अच्छा सवाल। मैं वास्तव में नहीं जानता कि कैसे mysql खुद के लिए 'स्मृति' रिजर्व करता है। यदि यह ओएस एपीआई के माध्यम से जाता है, तो यह सिर्फ स्मृति के लिए * पूछता है *, जिसे सिस्टम की स्थिति के अनुसार * * राम * या * हार्डड्राइव * स्पेस के रूप में कार्य किया जाएगा। विंडोज़ वर्चुअल बाइट्स प्रबंधन देखें। – Sebas

+0

क्या आपने तुलना के लिए 'तालिका बनाएं ... SELECT'-type क्वेरी' की कोशिश की है? http://dev.mysql.com/doc/refman/5.0/en/create-table-select.html – xiankai

उत्तर

0

कारण यह है कि कंप्यूटर कैसे पढ़ता है और लिखता है और जिस तरह से एक temp फ़ाइल काम करता है। चयन डेटा को पढ़ रहा है जो हार्ड ड्राइव पर अनुक्रमित फ़ाइल में है जबकि डालने एक अस्थायी फ़ाइल का उपयोग कर रहा है और उस फ़ाइल को लिख रहा है। अधिक रैम की आवश्यकता है और ऐसा करना अधिक कठिन है। क्यों एक मिनट लगते हैं, मुझे यकीन नहीं है लेकिन मुझे लगता है कि कोड थोड़ा गलत हो सकता है जिससे योगदान मिलेगा।

+0

मेरी अस्थायी तालिका का इंजन स्पष्ट रूप से 'स्मृति' पर सेट है। इसका मतलब यह नहीं है कि यह रैम में रहना चाहिए? मेरी मशीन में 32 जीबी रैम है जिसमें से 3 9 % का उपयोग किया जाता है। और मेरी अस्थायी तालिका में केवल 1000 पंक्तियां हैं ... – Ben

+0

@ben wehich os? – Sebas

+0

@ सेसस मेरा अपडेट देखें। – Ben

1

मैंने ऊपर एक टिप्पणी लिखी, फिर इसे एक कामकाज के रूप में ठोकर खाई।

यह वह करेगा जो आप करना चाहते हैं।

SELECT * FROM aTable INTO OUTFILE '/tmp/atable.txt'; 
LOAD DATA INFILE '/tmp/atable.txt' INTO TABLE anotherTable; 

ध्यान दें कि इसका मतलब है कि किसी भी तरह से/tmp टेबल प्रबंधित करना। यदि आप किसी आउटफाइल में डेटा को चुनने का प्रयास करते हैं जो पहले से मौजूद है, तो आपको एक त्रुटि मिलती है। तो आपको अद्वितीय अस्थायी फ़ाइल नाम उत्पन्न करने की आवश्यकता है। और उसके बाद उन्हें साफ करने के लिए किसी प्रकार का एक क्रॉन नौकरी चलाएं।

मुझे लगता है कि INFILE और आउटफाइल अलग-अलग व्यवहार करते हैं। यदि कोई mysql व्यवहार को समझाने के लिए यहां क्या हो रहा है, इस पर कुछ प्रकाश डाल सकता है, तो मैं इसकी सराहना करता हूं।

डी

यहाँ INFILE/outfile का उपयोग करने से एक बेहतर तरीका है।

सेट ट्रांज़ेक्शन इस्लामी स्तर पढ़ा गया; INSERT INTO atable का चयन करें ... से ...

यहाँ पढ़ने के लिए एक प्रासंगिक पोस्ट है:

How to improve INSERT INTO ... SELECT locking behavior

1

मैं एक ही मुद्दा होता है और वहां सबक्वेरी है कि वास्तव में इसे हल के साथ चारों ओर खेल रहा था। यदि चयन में बड़ी संख्या में पंक्तियां हैं, तो डेटा डालने में बहुत लंबा समय लगता है। उदाहरण:

INSERT INTO b2b_customers (b2b_name, b2b_address, b2b_language) 
SELECT customer_name, customer_address, customer_language 
FROM customers 
WHERE customer_name LIKE "%john%" 
ORDER BY customer_created_date DESC 
LIMIT 1 

संयोजन में सीमा का उपयोग डेटा डालने के लिए एक अच्छा विकल्प नहीं है। तो आप डेटा प्राप्त करने और डालने के लिए 2 अलग-अलग प्रश्नों का उपयोग कर सकते हैं, या आप एक सबक्वायरी का उपयोग कर सकते हैं। उदाहरण:

INSERT INTO b2b_customers (b2b_name, b2b_address, b2b_language) 
SELECT * FROM (
SELECT customer_name, customer_address, customer_language 
FROM customers 
WHERE customer_name LIKE "%john%" 
ORDER BY customer_created_date DESC 
LIMIT 1 
) sub1 

कि अपनी स्क्रिप्ट को बदले बिना एक तेजी से समाधान होगा।

तो मुझे यकीन नहीं है कि यह सबकुरी चलाने के लिए 0.01 सेकंड क्यों लेता है और सम्मिलित करने के लिए 60 सेकंड का समय लगता है। मुझे सीमा के बिना 1000+ परिणाम मिलते हैं। मेरे मामले में subquery 60 सेकंड से 0.01 सेकंड में प्रदर्शन में सुधार हुआ।

+0

आपको यकीन नहीं है कि यह एक मिलीसेकंड ** ** पढ़ने के लिए क्यों लेता है ** डेटा 60 सेकंड के लिए ** ** 1000+ रिकॉर्ड लिखें? शायद क्योंकि लेखन लिखने से तेज है? – Mjh

+0

हां, यह सच है, लेकिन मैं LIMIT 1. – joevette

+0

का उपयोग करते समय केवल 1 पंक्ति लिख रहा हूं, जहां ग्राहक_नाम LIKE "% जॉन%" है - यह एक पूर्ण तालिका स्कैन है। एक बार प्रत्येक एकल रिकॉर्ड स्कैन किया जाता है और 'जॉन' में पुनर्प्राप्त करने के लिए कम किया जाता है। इसमें कुछ समय लगता है। फिर आप 1 रिकॉर्ड लिखते हैं। यह अक्षम है। – Mjh

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