【问题标题】:How to run some jobs in parallel如何并行运行一些作业
【发布时间】:2017-05-20 05:01:42
【问题描述】:

在阅读了所有关于 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

然后加入线程。

实际上这些表是并行删除还是一个接一个?

【问题讨论】:

  • 为什么要并行删除它们=?如果您能解释其背后的原因会有所帮助吗?
  • @MuhammadAbdullah 以节省时间。如果我并行执行它会比我一个接一个地执行它更快。 (其实我有1K张表,需要对每张表进行预处理,为每张表独立添加记录。如果我连续做的话会慢一些。如果我对每张表并行做,会更快)
  • 通常,Sidekiq 或 jRuby 用于并行任务。阅读更多关于 Ruby 的 GIL(尤其是 MRI GIL)
  • @Ilya gem Parallel 怎么样?
  • 乍一看,它似乎也可以作为一种救援。但是,实际上,我没有尝试过。

标签: ruby parallel-processing


【解决方案1】:

原则上,您可以并行运行多个 SQL 语句。大多数数据库引擎都是多线程的,可以并行执行多个语句,但有时它并没有多大意义,比如使用 SQLite。

有几个警告可能会破坏您当前的代码。

最重要的是,与数据库的单个连接总是附加一些状态。通常,它将保存数据库适配器的事务和内部状态。因此,单个数据库连接通常一次只能在单个线程中使用。如果您尝试通过单个连接发送多个并行语句,事情可能会非常不确定地中断。

因此,当尝试使用线程并行运行多个语句时,每个线程都需要自己的数据库连接。在这里,使用线程池通常是有意义的,它创建固定的上限数量的连接并从队列中安排工作以在这些连接上运行。

你可以使用例如Rails 的ConnectionPool 用于处理数据库连接并使用优秀的concurrent-ruby gem 中的ThreadPool implementations 之一安排您的语句。

【讨论】:

  • ConnectionPool 是 ActiveRecord 的一部分,这并不一定意味着使用 Rails。没有理由仅仅为此而引入 Rails 堆栈。 ActiveRecord 的一个很好的替代品是 Sequel。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 2023-03-29
  • 2020-05-05
  • 2018-10-20
  • 2021-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多