2017-01-05 6 views
0

Прочитав все сообщения о параллелизме в Ruby, я только смутился, поэтому опишу, что я хочу делать.Как выполнять некоторые задания параллельно

У меня есть names, который содержит около 1000 имен.

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 

Но, я не хочу бросать столы один за другим. Я хочу сделать это параллельно.

Моя идея заключается в том, чтобы использовать следующее:

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

Зачем вы хотите сбросить их параллельно =? Если бы вы могли объяснить причину этого, это было бы полезно? – Abdullah

+0

@MuhammadAbdullah, чтобы сэкономить время. если я делаю это параллельно, это будет быстрее, чем если бы я делал это один за другим. (На самом деле, у меня есть 1K-таблицы, мне нужно предварительно обрабатывать каждую таблицу, добавлять записи независимо для каждой таблицы. Если я делаю это в строке, она будет медленной. Если я делаю это параллельно для каждой таблицы, это будет быстрее) – Tonja

+0

Обычно Sidekiq или jRuby используются для параллельных задач. Подробнее о Ruby's GIL (особенно MRI GIL) – Ilya

ответ

0

В принципе, вы можете запускать несколько операторов SQL параллельно. Большинство движков базы данных являются многопоточными и могут выполнять несколько операторов параллельно. Иногда это не имеет особого смысла, как при использовании SQLite.

Существует несколько предостережений, которые, вероятно, нарушат ваш текущий код.

Самое главное, что одно соединение с вашей базой данных всегда имеет определенное состояние. Зачастую он будет хранить транзакции и внутреннее состояние адаптера базы данных. Таким образом, одно соединение с базой данных обычно используется только в одном потоке за раз. Если вы попытаетесь отправить несколько параллельных операторов по одному соединению, все, вероятно, сломается довольно-детерминистически.

Таким образом, при попытке запуска нескольких операторов параллельно с использованием потоков каждому потоку требуется собственное соединение с базой данных. Здесь часто имеет смысл использовать пулы потоков, которые создают фиксированное верхнее число подключений и выполняют расписание работы из очереди для запуска на них.

Можно использовать, например, Rails 'ConnectionPool, чтобы обрабатывать соединения с базой данных и планировать свои заявления, используя один из ThreadPool implementations от отличного драгоценного камня concurrent-ruby.

+0

ConnectionPool является частью ActiveRecord, что не обязательно означает использование Rails. Для этого нет причин тянуть в стек Rails. Отличная альтернатива ActiveRecord - сиквел. –

Смежные вопросы