2017-01-05 12 views
0

Rubyでの並列性に関するすべての記事を読んだあと、混乱してしまいました。いくつかのジョブを並行して実行する方法

約1000の名前を含むnamesがあります。

names 
=> [{"name"=>"tickets"}, {"name"=>"events"}, {"name"=>"channel"}, {"name"=>"primes"}] 

各名前について、pgを使用している場合はテーブルを削除したいと思います。

drop_str = "DROP TABLE IF EXISTS %s ;" 
create_str = "CREATE TABLE %s (id SERIAL PRIMARY KEY,bkk varchar(255))" 

names.each do |name| 
    conn.exec((drop_str % name["name"]) + (create_str % name["name"])) 
end 

しかし、私はテーブルを1つずつ削除したくありません。私はそれを並行してやりたい

threads = [] 
drop_str = "DROP TABLE IF EXISTS %s ;" 
create_str = "CREATE TABLE %s (id SERIAL PRIMARY KEY,bkk varchar(255))" 

names.each do |name| 
    threads.push(Thread.new{conn.exec((drop_str % name["name"]) + (create_str % name["name"]))}) 
end 

して、スレッドに参加する:

私の考えでは、以下を使用することです。

実際にはテーブルは並行して削除されますか、それとも1つずつ削除されますか?

+1

なぜそれらを並列にドロップしたいですか?その背後にある理由を説明できれば助けになるだろうか? – Abdullah

+0

@MuhammadAbdullahは時間を節約します。私がそれを並行して実行すると、それを次々に行うよりも速くなります。 (実際には、私は1Kのテーブルを持っているので、各テーブルを前処理し、各テーブルごとに独立してレコードを追加する必要があります。 ) – Tonja

+0

通常、SidekiqまたはjRubyは並列タスクに使用されます。 RubyのGIL(特にMRI GIL)の詳細を読む – Ilya

答えて

0

原則として、複数のSQL文を並列に実行できます。ほとんどのデータベースエンジンはマルチスレッドであり、複数のステートメントを並列に実行できます。SQLiteを使用する場合と同じように、時にはそれほど意味をなさない場合もあります。

おそらくあなたの現在のコードを破壊するいくつかの警告があります。

データベースへの単一の接続には、常にいくつかの状態が関連付けられています。しばしば、トランザクションとデータベースアダプタの内部状態を保持します。したがって、単一のデータベース接続は、一般に、一度に1つのスレッドでのみ使用可能です。 1つの接続で複数のパラレル・ステートメントを送信しようとすると、事実上かなり決定的に破損することになります。

スレッドごとに複数のステートメントを並列に実行しようとすると、スレッドごとに独自のデータベース接続が必要になります。ここでは、一定数の接続を作成し、キューから作業をスケジュールするスレッドプールを使用することがよくあります。

たとえば、 RailsのConnectionPoolは、データベース接続を処理し、concurrent-ruby gemのThreadPool implementationsのいずれかを使用して文をスケジュールします。

+0

ConnectionPoolはActiveRecordの一部ですが、Railsを使用する必要はありません。そのためにRailsスタックを引き込む理由はありません。 ActiveRecordの優れた代替案はSequelです。 –

関連する問題