ruby - SQLite3 Activerecord 太慢

标签 ruby performance activerecord sqlite

我一直在为 sqlite(无导轨)使用 activerecord 适配器,当我尝试插入任何东西时,它似乎太慢了。例如,当我执行 ~250 次插入时,很容易花费超过 5 分钟!我的架构如下:

create_table :courses do |t|
    t.string :title
    t.integer :ethmmy_id
end

add_index :courses, :ethmmy_id

create_table :announcements do |t|
    t.string :title
    t.string :author
    t.string :body
    t.string :uhash
    t.belongs_to :courses
    t.timestamps null: false
end

add_index :announcements, :courses_id

我使用的 ActiveRecord 模型如下:

class Course < ActiveRecord::Base
    validates :ethmmy_id, uniqueness: true
    has_many :announcements
end

class Announcement < ActiveRecord::Base
    validates :uhash, uniqueness: true
    belongs_to :course
end

我试过修改 PRAGMAS,例如在内存中设置日志或关闭同步 I/O,但似乎没有太大区别。数据是从网络爬虫获取的,但这不是瓶颈,因为爬虫本身就非常快。

更具体地说,我注意到它每 10 个左右的插入就会卡住一次以写入数据库,但它似乎很慢。我试过像这样将创作添加到单个事务中:

ActiveRecord::Base.transaction do
    Course.all.each do |course|
         Announcement.create(....)
    end
end

但仍然没有性能提升。

为了测试,我什至尝试将整个数据库放入 more 中,整个过程仍然需要大约 5 分钟才能插入 250 次。调试日志显示每个 SQL 查询只有大约 0.1-0.2 毫秒,并且在某些插入(每次相同的插入)时,整个事情似乎在那里卡住了几秒钟。

更新: 在使用 ruby​​-prof 找到大部分时间花费的地方后,我发现 80% 甚至更多的时间都花在了 IO.select 上。这个方法是什么,叫什么?

最佳答案

您是否考虑过改用 mysql 而不是 sqlite?

无论如何,一种使插入速度更快的方法是在原始 sql 中而不是通过 activerecord 执行它们。每次您调用 create 时,都会触发近 10 个回调之类的东西。

创建一个单独的 sql 查询来插入一大堆数据可以像这样:

base_sql = 'INSERT INTO announcements (`title`, `author`, `body`, `uhash`, `course_id`) VALUES '
announcements = []
Course.all.each do |course|
  announcements << [title, author, body, uhash, course.id]
end

values_sql = announcements.map { |announcement| "(#{announcement.join(', ')})" }.join(', ')
ActiveRecord::Base.connection.execute(base_sql + values_sql)

当然,您必须用实际值替换您放置在 announcements 数组中的内容。

我在我的一个项目中使用了类似的东西,我们在不到一分钟的时间内在我的笔记本电脑上创建了 38000 条记录。

由于主要的性能优势之一是不会触发任何回调,因此您可以根据 activerecord 验证插入非法数据。记住并考虑这一点很重要。

唯一性验证可能会由您的数据库强制执行,但它可能仍会强制执行。

关于ruby - SQLite3 Activerecord 太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28974772/

相关文章:

node.js - NodeJS通过流复制文件非常慢

activerecord - Rails 3.1.1 ActiveRecord table_name= 不起作用

ruby-on-rails - 无效的多字节字符 (US-ASCII) 错误

java - Android应用程序的多语言支持

ruby - 使用 click_link 时错误的 URI(不是 URI?)

c# - 替换模板中字符串的最快方法

ruby-on-rails - Rails动态在数据库中创建表

ruby-on-rails - 使用 Postgres 查询哈希数组的数组

ruby-on-rails - 如何查找*所有*匹配类别的项目

ruby - 在 Ruby 中执行多个要求的最佳方法是什么?