避免在大型数据集中进行N + 1查询

时间:2018-11-14 22:27:11

标签: mysql sql ruby-on-rails

我有一个迁移,该迁移使用新的属性值更新现有记录。该模型称为“ MyRecord”。它在数据库中具有数百万条记录,其中新的unit_id列为null。我想用特定值更新该unit_id列:

MyRecord.find_each do |record|
  unit_id = Unit.calculate_unit_from_old_columns(record.legacy_column_1, record.legacy_column_2).first.id
  record.update unit_id: unit_id
end

这会创建很多N + 1个查询:

SELECT units.* FROM units WHERE units.item_1 = 'Electronics' AND units.item_2 = 'Auto' 
UPDATE my_records SET unit_id='43' WHERE legacy_column_1 = 'Legacy Electronics' AND legacy_column_2 = 'Legacy Auto';

其中一些N + 1查询重复。我在日志中看到了很多:

SELECT units.* FROM units WHERE units.item_1 = 'Electronics' AND units.item_2 = 'Auto' 
SELECT units.* FROM units WHERE units.item_1 = 'Electronics' AND units.item_2 = 'Auto' 

我熟悉通过include进行快速加载的过程。但是,当运行此迁移以更新现有数据时,将没有关联。所以我不能这样做:

record.includes(:unit)

如何消除N + 1个查询并缓存该查询,以便在重复查询时它不会再次访问数据库?

1 个答案:

答案 0 :(得分:0)

使用一个简单的查询,如果运行时间过长,您可以考虑对其进行批处理:

or:0, ow:1
or:0, ow:1
or:0, ow:1