Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ActiveRecord N+1 count queries #shibuyarb

ActiveRecord N+1 count queries #shibuyarb

Takashi Kokubun

July 15, 2015
Tweet

More Decks by Takashi Kokubun

Other Decks in Programming

Transcript

  1. How$do$you$defeat$this? User.all.each do |user| user.tweets.count end # SELECT `users`.* FROM

    `users` # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 1 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 2 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 3 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 4 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 5
  2. OK,$cache$it$:) User.all.each do |user| user.tweets_count end class Tweet < ActiveRecord::Base

    belongs_to :user, counter_cache: true end # SELECT `users`.* FROM `users` ͦΕ͕!Rails!way
  3. ແݶʹ૿͑ଓ͚ΔΧϥϜ CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT,

    `tweets_count` int(11) NOT NULL DEFAULT '0', `replies_count` int(11) NOT NULL DEFAULT '0', `favorites_count` int(11) NOT NULL DEFAULT '0', `retweets_count` int(11) NOT NULL DEFAULT '0', `followers_count` int(11) NOT NULL DEFAULT '0', `following_count` int(11) NOT NULL DEFAULT '0', -- …
  4. ͜ΕΛͳ User.all.each do |user| user.tweets.count end # SELECT `users`.* FROM

    `users` # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 1 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 2 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 3 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 4 # SELECT COUNT(*) FROM `tweets` WHERE `tweets`.`user_id` = 5
  5. ͜͏͡Ό User.all.precount(:tweets).each do |user| user.tweets.count end # SELECT `users`.* FROM

    `users` # SELECT COUNT(`tweets`.`user_id`), `tweets`.`user_id` FROM # `tweets` WHERE `tweets`.`user_id` IN (1, 2, 3, 4, 5) # GROUP BY `tweets`.`user_id`
  6. JOIN΋؆୯ User.all.eager_count(:tweets).each do |user| user.tweets.count end # SELECT `users`.`id` AS

    t0_r0, `users`.`created_at` AS t0_r3, # `users`.`updated_at` AS t0_r4, COUNT(`tweets`.`id`) AS t1_r0 # FROM `users` LEFT OUTER JOIN `tweets` # ON `tweets`.`user_id` = `users`.`id` GROUP BY users.id