2009-10-01 18 views
8

मैं एक PostgreSQL क्वेरी जो एक बड़ी परिणाम देता है निष्पादित करने के लिए कोशिश कर रहा हूँ से बाहर दे:JDBC + बड़े PostgreSQL क्वेरी स्मृति

connection.setAutoCommit(false); 
st = connection.createStatement(
    ResultSet.CONCUR_READ_ONLY, 
    ResultSet.TYPE_FORWARD_ONLY 
); 
st.setFetchSize(100); 
logMemory(); 
System.out.println("start query "); 
rs = st.executeQuery(queryString); 
System.out.println("done query "); 
logMemory(); 

लेकिन यह स्मृति का एक बहुत का उपयोग करता है:

Free memory; 4094347680 (= 3905 mb). 
start query 
done query 
Free memory; 2051038576 (= 1956 mb). 

(Runtime.getRuntime() के साथ मुद्रित। फ्रीमेमरी())

अब तक यह काम करता है लेकिन डेटाबेस बहुत बड़ा होगा। मुझे स्मृति में पूरे परिणाम की आवश्यकता नहीं है; मुझे बस प्रत्येक पंक्ति को खरीदने की आवश्यकता है, परिणाम डिस्क पर लिखें और अगली पंक्ति पर जाएं।

मुझे पता है कि 'setFetchSize' केवल एक संकेत है, लेकिन अगर मैं postgresql/jdbc इसे अनदेखा कर दूंगा, तो मुझे यह अजीब लगेगा, क्योंकि यह उम्र के आसपास है।

इस के आसपास पाने के लिए कोई भी तरीका है? मेरा एकमात्र विचार अब तक एक बैच स्क्रिप्ट बनाना है जो क्वेरी के परिणाम को डिस्क पर स्ट्रीम करता है और फिर जावा से फ़ाइल को पार्स करता है ...

+0

बस उत्सुक है, आप जिस अधिकतम ढेर आकार के साथ चल रहे हैं? या आप डिफ़ॉल्ट का उपयोग कर रहे हैं? –

+1

यह -Xmx4096M -Xms4096M है, यह विस्टा 8 जीबी मशीन है। – kresjer

उत्तर

7

ओच, यह मैंने देखा है कि जेडीबीसी का उपयोग कर सबसे बुरा कीड़े में से एक है। आप

st = connection.createStatement(
    ResultSet.CONCUR_READ_ONLY, 
    ResultSet.TYPE_FORWARD_ONLY 
); 

बदलना चाहिए

st = connection.createStatement(
    ResultSet.TYPE_FORWARD_ONLY, 
    ResultSet.CONCUR_READ_ONLY 
); 

में हो सकता है कि बस

st = connection.createStatement(); 

रूप में अच्छी तरह से काम करेगा (के रूप में आप एक कर्सर के लिए अन्य मानदंड पूरा करते हैं)।

+0

बग क्या है? क्या यह वास्तविक स्मृति रिसाव है या कुछ और चल रहा है? क्या आपको लगता है कि यह केवल पोस्टग्रेस है? – rogerdpack

+0

@rogerdpack OP ने 'createStatement' के लिए विधि पैरामीटर बदल दिए। दोनों पैरामीटर 'int's हैं लेकिन इसका मतलब कुछ अलग-अलग चीजें हैं। तो यह जेडीबीसी कार्यान्वयन में कोई भी बग नहीं है। –

9

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

+0

हाँ, मैंने सभी दिशानिर्देशों को चालू/बंद करने का प्रयास किया है। कथन बस डेटा से hh.data, hh.customer_ID का चयन करें एचएच hh.customer_ID = PH.customer_ID पर ग्राहक पीएच में शामिल हों; और यह postgresql 8.3 है और मैं postgresql-8.3-603.jdbc4.jar का उपयोग कर रहा हूं। – kresjer

+0

मैं स्टंप हो गया हूँ। मैं कहूंगा कि अगला सबसे अच्छा कदम उन समूहों पर पोस्ट करना है जो पोस्टग्रेस्क्ल पर ध्यान केंद्रित करते हैं। शायद कुछ अन्य गैर-स्पष्ट चीजें हैं जो कर्सर का उपयोग करने के लिए कनेक्शन को मजबूर कर सकती हैं। मैं जेडीबीसी स्रोत कोड खोलता हूं (यह ओपन सोर्स के बारे में अच्छी बात है) और देखें कि आपके परिदृश्य में क्या चल रहा है। – Yishai

+1

उत्तर के लिए बहुत बहुत धन्यवाद। जब तक मैंने उद्धृत पृष्ठ पर 'conn.setAutoCommit (false)' की आवश्यकता नहीं पाई, तब तक मैं पूरे दिन इस समस्या से जूझ रहा था। – jutky

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