如何避免 Rails 4 中的预加载问题
How to avoid eagerloading problem in Rails 4
下面是我的代码。
客户端在 'events' table
中有许多带有外键 client_id 的事件
has_many :events
在控制台中
clients = Client.where(id: [110,112,113,115]).includes(:events)
=> Client Load (0.4ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`id` IN (110, 112, 113, 115)
Event Load (0.5ms) SELECT `events`.* FROM `events` WHERE `events`.`client_id` IN (110, 112, 113, 115)
但是当运行关注时,
clients.each { |cr| cr.events.count }
(0.4ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 110
(0.3ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 112
(0.3ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 113
(0.3ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 115
我收到 N+1 个查询,我遗漏了一些东西。
更新
从我得到线索的答案中,我想要事件的 ID,所以我正在尝试,
clients.each { |cr| cr.events.ids }
clients.each { |cr| cr.events.pluck(:id) }
所以 N+1 个查询被解雇了,然后我用下面的方法解决了,
clients.each { |cr| cr.events.map(&:id) }
我将关系视为数组并使用 map
而不是 ids
或 pluck
并解决了,没有触发 N+1 查询。
.count
在 ActiveRecord 关系的情况下将简单地 运行 查询。如果您将其更改为 .size
,将检查预加载项目数组的长度,这就是您所追求的。
如果您的目标是获取事件 ID,请使用 join with pluck
event_ids = Client.where(id: [110,112,113,115]).joins(:events).pluck('events.id')
下面是我的代码。
客户端在 'events' table
中有许多带有外键 client_id 的事件has_many :events
在控制台中
clients = Client.where(id: [110,112,113,115]).includes(:events)
=> Client Load (0.4ms) SELECT `clients`.* FROM `clients` WHERE `clients`.`id` IN (110, 112, 113, 115)
Event Load (0.5ms) SELECT `events`.* FROM `events` WHERE `events`.`client_id` IN (110, 112, 113, 115)
但是当运行关注时,
clients.each { |cr| cr.events.count }
(0.4ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 110
(0.3ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 112
(0.3ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 113
(0.3ms) SELECT COUNT(*) FROM `events` WHERE `events`.`client_id` = 115
我收到 N+1 个查询,我遗漏了一些东西。
更新
从我得到线索的答案中,我想要事件的 ID,所以我正在尝试,
clients.each { |cr| cr.events.ids }
clients.each { |cr| cr.events.pluck(:id) }
所以 N+1 个查询被解雇了,然后我用下面的方法解决了,
clients.each { |cr| cr.events.map(&:id) }
我将关系视为数组并使用 map
而不是 ids
或 pluck
并解决了,没有触发 N+1 查询。
.count
在 ActiveRecord 关系的情况下将简单地 运行 查询。如果您将其更改为 .size
,将检查预加载项目数组的长度,这就是您所追求的。
如果您的目标是获取事件 ID,请使用 join with pluck
event_ids = Client.where(id: [110,112,113,115]).joins(:events).pluck('events.id')