![](/img/trans.png)
[英]How to combine these two queries into one optimized query to avoid a Select N+1
[英]Avoid N+1 query in large data set
我有一个迁移,它使用新的属性值更新现有记录。 该模型称为“ 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'
我熟悉通过包含加载的渴望。 但是,当运行此迁移以更新现有数据时,将没有关联。 所以我不能这样做:
record.includes(:unit)
如何消除N + 1个查询并缓存该查询,以便在重复查询时它不会再次命中数据库?
使用简单的查询,如果运行时间过长,您可以考虑对其进行批处理:
MyRecord.connection.execute(
"UPDATE my_records, units
SET unit_id = units.id
WHERE units.item_1 = legacy_column_1 AND units.item_2 = legacy_column_2"
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.