【问题标题】:Efficient way to get data from an array of non primary-key IDs?从非主键 ID 数组中获取数据的有效方法?
【发布时间】:2014-09-09 19:26:18
【问题描述】:

我有一个 Ruby/Sinatra 应用程序,我在其中接收和解析图像的 JSON 字符串,例如:

[{"id" => "ABCD123", "type" => "image"},
 {"id" => "ABCD234", "type" => "image"},
 {"id" => "ABCD345", "type" => "image"},
 {"id" => "ABCD456", "type" => "image"},
 {"id" => "ABCD567", "type" => "image"}]

在数据库中,我有许多行存储图像的标题。目前,我有一个遍历数组并执行以下操作的函数:

app.rb

def get_caption(image_id)
  caption = Images.find_by_image_id image_id
end

index.haml

-images.each do |image|
  %div= get_caption(image['id'])

这似乎非常低效,因为该网站对每张图片进行了独特的查找,这肯定会增加页面的加载时间。

Images Load (131.6ms)  SELECT  "images".* FROM "images"  WHERE "images"."image_id" = 'ABCD123' LIMIT 1
...
Images Load (131.6ms)  SELECT  "images".* FROM "images"  WHERE "images"."image_id" = 'ABCD567' LIMIT 1

131.6ms * n 查询确实加起来很快(我希望在我们为生产进行优化时,这种缓慢的约 130 毫秒查找将得到改善,但也许这将是以后的另一个问题!)。

有没有更有效的方法来进行这种查找?以某种方式将caption 字段加入到数组中?

【问题讨论】:

  • 而不是运行单独的查询,where in (x,y,z,....) 类型构造可能会有所帮助。在 image_id 字段上设置索引也会有所帮助。

标签: ruby postgresql activerecord sinatra


【解决方案1】:

写成

def get_captions(image_ids)
  caption = Images.where(image_id: image_ids)
end

image_ids = images.map { |image| image['id'] }
get_captions(image_ids)

【讨论】:

    【解决方案2】:

    你可以做两件事来优化它:

    1. 一次从数据库中获取所有需要的数据,而不是循环:

      Images.where(image_id: image_ids).index_by(&:image_id)
      
    2. 在数据库中的image_id 列上创建二级索引:

      add_index :images, :image_id
      

    我想强调一些违反 Rails 惯例的其他事情:

    1. 模型名必须是单数,表名必须是复数。这意味着模型的名称应该是Image
    2. 我可能错了,但看起来查询是在视图或助手中进行的。所有数据库查询都应该在模型中,除了可以在控制器中的“按主键查找”。

    【讨论】:

    • 所有好建议。如果图像具有超出正常行 ID 的唯一 ID,则 image_id 列上的二级索引可能会很好。我可能会依赖行 ID 作为唯一标识符和围绕它的代码,但这只是我。而且我以后可能会找到一些我不喜欢这样的原因。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2017-02-26
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    相关资源
    最近更新 更多