स्प्लिट के साथ जीएनयू समानांतर का उपयोग करना


9

मैं एक postgresql डेटाबेस के लिए एक बहुत बड़ी फ़ाइल लोड कर रहा हूँ। इस मैं पहली बार उपयोग करने के लिए splitफ़ाइल में छोटे फ़ाइलें (30GB प्रत्येक) प्राप्त करने के लिए और फिर मैं का उपयोग कर डेटाबेस के लिए प्रत्येक छोटे फ़ाइल लोड GNU Parallelऔर psql copy

समस्या यह है कि फ़ाइल को विभाजित करने में लगभग 7 घंटे लगते हैं, और फिर यह प्रति कोर फ़ाइल लोड करना शुरू कर देता है। मुझे यह बताने splitका तरीका है कि फाइल का नाम प्रिंट करने के लिए एसटीडी आउटपुट हर बार फाइल लिखने के बाद मैं इसे पाइप कर सकता हूं Parallelऔर यह फाइल splitलिखने के समय पर फाइल लोड करना शुरू कर देता है। कुछ इस तरह:

split -l 50000000 2011.psv carga/2011_ | parallel ./carga_postgres.sh {}

मैंने splitमैन पेज पढ़े हैं और मुझे कुछ नहीं मिल रहा है। क्या ऐसा करने का कोई तरीका है splitया किसी अन्य उपकरण के साथ?

जवाबों:


13

का प्रयोग करें - पकाने की विधि:

cat 2011.psv | parallel --pipe -l 50000000 ./carga_postgres.sh

इसके लिए आवश्यकता होती है। /carga_postgres.sh को एक फ़ाइल से पढ़ने के लिए न कि स्टड से, और यह जीएनयू समानांतर संस्करण <20130222 के लिए धीमा है।

यदि आपको वास्तव में 50000000 लाइनों की आवश्यकता नहीं है - तेज़ तेज़ है:

cat 2011.psv | parallel --pipe --block 500M ./carga_postgres.sh

यह \ n पर लगभग 500MB विभाजन का हिस्सा होगा।

मुझे नहीं पता कि क्या है ।/carga_postgres.sh सम्‍मिलित है, लेकिन मेरा अनुमान है कि इसमें उपयोगकर्ता नाम पासवर्ड के साथ psql है। उस स्थिति में आप GNU SQL (जो GNU समानांतर का हिस्सा है) का उपयोग करना चाहते हैं:

cat 2011.psv | parallel --pipe --block 500M sql pg://user:pass@host/db

प्रमुख लाभ यह है कि आपको अस्थायी फ़ाइलों को सहेजने की आवश्यकता नहीं है, लेकिन सभी मेमोरी / पाइप में रख सकते हैं।

अगर।

cat 2011.psv | parallel --pipe --block 500M "cat > {#}; ./carga_postgres.sh {#}"

बड़ी नौकरियां अक्सर आधे रास्ते से विफल हो जाती हैं। जीएनयू समानांतर असफल नौकरियों को फिर से चलाने में आपकी मदद कर सकता है:

cat 2011.psv | parallel --pipe --block 500M --joblog my_log --resume-failed "cat > {#}; ./carga_postgres.sh {#}"

यदि यह विफल रहता है तो आप उपरोक्त को फिर से चला सकते हैं। यह उन ब्लॉकों को छोड़ देगा जो पहले से ही सफलतापूर्वक संसाधित हैं।


1
यदि आपके पास GNU पैरेलल का नया संस्करण है> 20140422 @pipepart के साथ @ रॉबर्टबी के उत्तर का उपयोग करें। अगर वह सीधे काम नहीं करता है, तो देखें - अगर या तो - कैफ आपकी मदद कर सकता है।
ओले तांगे

2

जीएनयू समानांतर के साथ - पिप और - रिपेपार्ट का उपयोग क्यों नहीं किया जाता है? यह अतिरिक्त बिल्ली को समाप्त करता है और डिस्क पर फ़ाइल से प्रत्यक्ष रीड शुरू करता है:

parallel --pipe --pipepart -a 2011.psv --block 500M ./carga_postgres.sh

1

मुझे लगता है कि यहाँ पोस्ट किए गए उत्तर जटिल होने के लिए हैं, इसलिए मैंने स्टैक ओवरफ्लो पर पूछा और मुझे यह उत्तर मिला :

यदि आप उपयोग करते हैं GNU split, तो आप --filterविकल्प के साथ ऐसा कर सकते हैं

'--filter = कमांड'
इस विकल्प के साथ, केवल प्रत्येक आउटपुट फ़ाइल पर लिखने के बजाय, प्रत्येक आउटपुट फ़ाइल के लिए निर्दिष्ट शेल कमांड के लिए एक पाइप के माध्यम से लिखें। कमांड को $ FILE पर्यावरण चर का उपयोग करना चाहिए, जो कमांड के प्रत्येक आह्वान के लिए एक अलग आउटपुट फ़ाइल नाम पर सेट है।

आप एक शेल स्क्रिप्ट बना सकते हैं, जो एक फाइल बनाती है और बैकग्राउंड के अंत में carga_postgres.sh शुरू करती है

#! /bin/sh

cat >$FILE
./carga_postgres.sh $FILE &

और उस स्क्रिप्ट को फ़िल्टर के रूप में उपयोग करें

split -l 50000000 --filter=./filter.sh 2011.psv

0

splitफ़ाइल नाम प्रिंट करने का एक विकल्प यह पता लगाना है कि फाइलें कब तैयार होती हैं। लिनक्स पर, आप inotify सुविधा और विशेष रूप से inotifywaitउपयोगिता का उपयोग कर सकते हैं ।

inotifywait -m -q -e close_write --format %f carga | parallel ./carga_postgres.sh &
split -l 50000000 2011.psv carga/2011_

आपको inotifywaitमैन्युअल रूप से मारना होगा । इसे स्वचालित रूप से मारना थोड़ा कठिन है क्योंकि एक संभावित दौड़ की स्थिति है: यदि आप इसे splitखत्म होते ही मार देते हैं , तो हो सकता है कि यह उन घटनाओं को प्राप्त कर ले जो अभी तक रिपोर्ट नहीं की है। यह सुनिश्चित करने के लिए कि सभी ईवेंट रिपोर्ट किए गए हैं, मेल खाने वाली फ़ाइलों की गणना करें।

{
  sh -c 'echo $PPID' >inotifywait.pid
  exec inotifywait -m -q -e close_write --format %f carga
} | tee last.file \
  | parallel ./carga_postgres.sh &
split -l 50000000 2011.psv carga/2011_
(
  set carga/2011_??; eval "last_file=\${$#}"
  while ! grep -qxF "$last_file" last.file; do sleep 1; done
)
kill $(cat inotifywait.pid)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.