【问题标题】:Insert an element into a PostgreSQL array without overwriting it将元素插入 PostgreSQL 数组而不覆盖它
【发布时间】:2015-10-07 01:08:19
【问题描述】:

我想在 postgres 的数组列中插入一些数据。

sample_model = MyModel.create
100.times do
  sample_model.array.push [Time.now.to_i, 1234]
  sample_model.save  
end

这需要 0.5 秒才能完成,而且效率非常低。此代码每次都会覆盖数组。使用 mongoDB 和 mongoid 的相同代码大约需要 0.08 秒才能完成。

sample_model = MyMongoidModel.create
100.times do
  sample_model.push(array: [[Time.now.to_i, 1234]]) 
end

有没有办法像 mongo 那样将元素插入到 postgres 数组列?我什至会考虑任何纯 SQL 解决方案。

【问题讨论】:

  • 在 SQL 中,您只需执行 array_column || 1234 即可将值附加到数组的末尾。我对Rails 一无所知,但对我来说将模型保存在inside 循环中(顺便说一句,你不会为Mongo 做)看起来非常低效。我希望在循环之后保存模型一次就足够了
  • @a_horse_with_no_name 我应该写什么 ruby​​ 代码来做到这一点?谢谢。它只是一个示例代码。在现实生活中,我需要将一个元素附加到 1000 个元素的数组中,因此覆盖它并不是很有效。
  • 内部 PostgreSQL 无法就地更新数组。由于 MVCC 要求,它们总是复制到新行。如果您要大量更新字段,请使用带有连接表的关系设计,而不是数组。您可以通过拆分和连接来更新 SQL 中的数组,但您仍在用新数组编写新行,即使它看起来像更新。
  • @CraigRinger 我试着用连接表来做,我在 0.3 - 0.4 秒内完成了与上面相同的任务。不是很快。

标签: ruby-on-rails arrays ruby postgresql activerecord


【解决方案1】:

SQL 解决方案:

class MyModel < ActiveRecord::Base
  has_many :time_entries, dependent: :destroy, inverse_of: :my_model
end

class TimeEntry < ActiveRecord::Base
  belongs_to :my_model, inverse_of :time_entries
  validates_presence_of: time
end

100.times {MyModel.last.time_entries.create(time: Time.now)}

【讨论】:

    【解决方案2】:

    你有没有读过这个:https://www.coffeepowered.net/2009/01/23/mass-inserting-data-in-rails-without-killing-your-performance/

    我认为 选项 3 - 单个质量插入 是您正在寻找的。​​p>

    【讨论】:

    • 这不是我的情况。上面的代码只是一个示例。我需要在已经有 1000 个元素的数组中插入一个新元素,然后保存该对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    相关资源
    最近更新 更多