Skip to content

Instantly share code, notes, and snippets.

@gregblake
Last active December 17, 2019 13:46
Show Gist options
  • Select an option

  • Save gregblake/b01c7709d60a7809214b29892864d95c to your computer and use it in GitHub Desktop.

Select an option

Save gregblake/b01c7709d60a7809214b29892864d95c to your computer and use it in GitHub Desktop.
Using ActiveRecord's Eager Loading Associations to Optimize a Query

This query optimization can be recreated locally, by running the following and grepping the logs (comparing the master branch to this feature branch).

Prior to this PR, the number of queries issued was dependent upon the number of rooms in the collection (N+1). In production, the collection often contains many rooms. Now, only two queries are issued, no matter how many rooms are in the collection.

From the Rails console:

rooms = Connect::Room.where(private: true, archived: false).first(10);
rooms.each do |room|
  Connect::Message.create(from_id: 618, to: room, body: "u#all");
end

# This simulates a run of the relevant thread on the notifications server:
Connect::NotificationsServer::PopulateRoomsAndPublishUpdates.call!

grep the logs for relevant entries:

tail -f log/development.log | grep "RoomMembership Load"

Without the changes on this PR (11 queries--1 query, plus a query for each room in the collection):

Connect::RoomMembership Load (2.2ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE (broadcaster = 1 and user_id is not null) AND `connect_room_memberships`.`connect_room_id` IN (59, 64, 92, 121, 126, 131, 138, 157, 164, 170)
Connect::RoomMembership Load (1.7ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 59
Connect::RoomMembership Load (1.6ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 64
Connect::RoomMembership Load (1.7ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 92
Connect::RoomMembership Load (1.2ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 121
Connect::RoomMembership Load (1.9ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 126
Connect::RoomMembership Load (1.2ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 131
Connect::RoomMembership Load (1.6ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 138
Connect::RoomMembership Load (1.4ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 157
Connect::RoomMembership Load (1.3ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 164
Connect::RoomMembership Load (1.5ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` = 170

The same code path, including the changes on this PR (2 queries, no matter how many rooms are in the collection):

Connect::RoomMembership Load (2.2ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE (broadcaster = 1 and user_id is not null) AND `connect_room_memberships`.`connect_room_id` IN (59, 64, 92, 121, 126, 131, 138, 157, 164, 170)
Connect::RoomMembership Load (2.6ms)  SELECT `connect_room_memberships`.* FROM `connect_room_memberships` WHERE `connect_room_memberships`.`connect_room_id` IN (59, 64, 92, 121, 126, 131, 138, 157, 164, 170)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment