【问题标题】:SQLite3 Activerecord is too slowSQLite3 Activerecord 太慢了
【发布时间】:2015-05-12 13:02:25
【问题描述】:

我一直在为 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

但仍然没有性能提升。

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

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

【问题讨论】:

    标签: ruby performance activerecord sqlite


    【解决方案1】:

    你有没有考虑改用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)
    

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

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

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

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

    【讨论】:

    • 关于这个主题的进一步阅读:coffeepowered.net/2009/01/23/…
    • 好吧,我想继续使用activerecord,因为它非常方便。所以我想我可以尝试一个合适的 DBMS。
    • 我已经阅读了那篇文章并尝试了一些建议,但没有任何收获
    • 插入的瓶颈在哪里?在数据库中花费了多少时间与在 activerecord 中花费了多少时间?
    • 您在运行本地环境吗?我通常查看我的 log/development.log。如果这通常是在某种 rake 任务中完成的,我想还有其他分析器。或者您可以将其移动到任何路线以进行调试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 2013-03-10
    • 2014-06-07
    • 2016-05-31
    • 2011-07-07
    • 2015-08-23
    • 2012-07-05
    相关资源
    最近更新 更多