জিএনইউ সমান্তরাল উইথ স্প্লিট ব্যবহার করে


9

আমি একটি পোস্টগ্র্যাসকিএল ডেটাবেজে একটি দুর্দান্ত দৈত্য ফাইল লোড করছি। এটি করার জন্য আমি প্রথমে splitফাইলটিতে ছোট ফাইল (প্রতিটি 30 জিবি) পাওয়ার জন্য ব্যবহার করি এবং তারপরে এবং প্রতিটি ব্যবহার করে ছোট ছোট ফাইলটি ডাটাবেসে লোড করি 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

এটি 500 n এ প্রায় 500MB বিভক্ত অংশগুলি পাস করবে।

./Carga_postgres.sh এর মধ্যে কী আছে তা আমি জানি না তবে আমার ধারণা এটিতে ব্যবহারকারীর পাসওয়ার্ড সহ পিএসকিএল রয়েছে। সেক্ষেত্রে আপনি জিএনইউ এসকিউএল (যা জিএনইউ সমান্তরালের অংশ) ব্যবহার করতে চাইতে পারেন:

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

প্রধান সুবিধাটি হ'ল আপনার অস্থায়ী ফাইলগুলি সংরক্ষণ করার দরকার নেই, তবে সমস্তগুলি মেমরি / পাইপগুলিতে রাখতে পারেন।

যদি ./carga_postgres.sh স্টিডিন থেকে পড়তে না পারে তবে একটি ফাইল থেকে পড়তে হবে তবে আপনি এটি একটি ফাইলে সংরক্ষণ করতে পারেন:

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
আপনার যদি জিএনইউ সমান্তরাল> 20140422 এর একটি নতুন সংস্করণ থাকে তবে @ রবিবার্টের উত্তর --pipepart ব্যবহার করুন। যদি এটি সরাসরি কাজ না করে তবে দেখুন --fifo বা --cat আপনাকে সাহায্য করতে পারে কিনা।
ওলে টাঞ্জ

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ফাইলগুলির নাম মুদ্রণ করার একটি বিকল্প হ'ল ফাইলগুলি কখন প্রস্তুত থাকে তা সনাক্ত করা। লিনাক্সে, আপনি ইনোটিফাই সুবিধা এবং বিশেষত 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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.