Double everything in my db logs Rails - ruby-on-rails

I have double everything in my logs. Not sure how to get rid of it. Any suggestions?
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 7]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 7]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 7]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 7]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 8]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 8]]
Size Load (0.3ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 8]]
Size Load (0.3ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 8]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 9]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 9]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 9]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 9]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 10]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 10]]
CACHE (0.0ms) SELECT "printers".* FROM "printers" WHERE "printers"."id" = $1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "printers".* FROM "printers" WHERE "printers"."id" = $1 LIMIT 1 [["id", 1]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 10]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 10]]
Rails Version Rails 4.2.5
Ruby Version 2.3.0

you can add the following to application.rb
if Rails.env.development?
# Don't log to STDOUT, by default rails s will handle it
config.logger = Logger.new('/dev/null')
else
# Don't log to file, sending everything to unicorn file.
config.logger = Logger.new(STDOUT)
end
Basically rails server and rails logger both send their messages to stdout which results in duplication in the logs.

Related

Rails 6.1 eager load ActiveStorage::VariantRecord

I have been eager loading ActiveStorage attachments as follows:
Journey.includes(created_by_user: [profile_picture_attachment: :blob])
We have been using variants and every since we upgraded to Rails 6.1 and enabled tracking Active Storage variants in database, we notice n+1 queries in the logs because of a loop as follows:
Journey.includes(created_by_user: [profile_picture_attachment: :blob]).each do |j|
j.created_by_user.profile_picture.variant(resize_to_fill: [32, 32]).processed
end
Journey Load (0.8ms) SELECT "journeys".* FROM "journeys"
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 607]]
ActiveStorage::Attachment Load (0.6ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_type" = $1 AND "active_storage_attachments"."name" = $2 AND "active_storage_attachments"."record_id" = $3 [["record_type", "User"], ["name", "profile_picture"], ["record_id", 607]]
ActiveStorage::Blob Load (0.6ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 [["id", 144]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
I tried to eager load with the following but it doesn't seem to work:
Journey.includes(created_by_user: [profile_picture_attachment: { blob: :variant_records }])
Has anyone tried eager loading the tracked variant records to share your ideas?
Turns out there is a pull request addressing exactly this. For anyone looking for a solution, please follow the merge request.
https://github.com/rails/rails/pull/37901
It eventually winds its way to a secondary PR, which allows eager loading the stored variants. It's now merged into future versions of Rails, here was the code they used to eager load variants:
https://github.com/rails/rails/pull/40842/files

Stop rails loading associated models when checkin if record is valid

I have an object called message which belongs to carrier, company, country
I allowing for a bulk insert of users via a CSV - what i want to do before is make sure every row is valid before i import it (so that i can inform the user prior to the beginning the import)
So i have created a method that loops through all new data and does Message.new(PARAMS_IN_HERE) and then call .valid? on it, which is fine and achieves the desired results.
However, when i look in the logs i see loads of queries like this
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.3ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Which is obviously quite wasteful as one its doing the same query multiple times. Is there a way to make rails cache the value/preload when it needs to look for/ or just stop it happening?
This is what my message class look like
class Message < ApplicationRecord
belongs_to :company
belongs_to :carrier
belongs_to :country
before_validation :set_default_details, on: :create
private
def set_default_details
if self.user.present?
self.carrier_id = self.user.company.tariff.carrier_id
self.country_id = self.user.country_id
self.company_id = self.user.company_id
end
end
end
Your validation references self.user but that's not defined in the model snippet you posted.
If your validations refer to to association objects, like self.company, give those objects to the constructor: Message.new(company: company) rather than Message.new(company_id: company.id). If necessary look up all dependent objects ahead of time - this can be done with a single query - and store id -> object mapping in a Hash.
Similarly you can have validations reference fields like company_id but it's probably better to use association objects everywhere.

Active Model Serializer - Increasing Render Performance

I'm running into a particular situation where the rendered json generated by ActiveModel::Serializer is extraordinary slow (around 6-8 seconds). How can I improve the speed of this rendering? Here's the code.
Models:
class Comment < ActiveRecord::Base
has_many :children_comments,
class_name: 'Comment',
foreign_key: 'parent_comment_id'
belongs_to :user
belongs_to :parent_comment,
class_name: 'Comment',
foreign_key: 'parent_comment_id'
end
Serializers:
class CommentSerializer < ActiveModel::Serializer
include ActionView::Helpers::DateHelper
attributes :id, :message, :created_at_in_words,
:created_at, :parent_comment_id
belongs_to :user
has_many :children_comments
def created_at_in_words
time_ago_in_words(object.created_at) + ' ago'
end
def children_comments
object.children_comments.map do |comment|
CommentSerializer.new(comment).as_json
end
end
end
class UserSerializer < ActiveModel::Serializer
attributes :id, :name, :avatar_url
def avatar_url
object.avatar.url
end
end
In my controller I have
parent_comments = Comment.where(parent_comment_id: nil)
render status: :ok,
json: parent_comments,
each_serializer: CommentSerializer,
key_transform: :camel_lower
Here is my partial log output when I make the call to the server. As you ca see Active Model Serializer is taking around 20ms to make each query call.
Started GET "/comments?lesson_id=420" for ::1 at 2016-09-01 11:09:14 -0400
Processing by Api::CommentsController#index as HTML
Parameters: {"lesson_id"=>"420"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 102]]
Lesson Load (0.5ms) SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = $1 ORDER BY position ASC LIMIT 1 [["id", 420]]
Comment Load (53.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2 AND "comments"."parent_comment_id" IS NULL [["commentable_id", 420], ["commentable_type", "Lesson"]]
[active_model_serializers] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (24.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41401]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41402]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41403]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (21.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41404]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41405]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41406]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41407]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41408]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41409]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41410]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41411]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41412]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41413]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (23.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41414]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41415]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41416]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (23.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41417]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41418]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41419]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41420]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41421]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41422]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41423]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41424]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41425]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41426]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41427]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41428]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41429]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41430]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41431]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41432]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41433]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (21.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41434]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41435]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (21.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41436]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41437]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41438]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41439]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41440]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41441]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41442]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41443]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41444]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41445]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41446]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41447]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41448]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41449]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41450]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41451]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41452]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41453]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41454]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41455]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41456]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41457]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41458]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41459]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41460]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41461]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41462]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41463]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41464]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41465]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41466]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41467]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41468]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41469]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41470]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41471]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41472]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41473]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41474]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41475]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41476]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41477]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41478]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41479]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41480]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41534]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41535]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41536]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41537]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41538]]
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Json (3895.33ms)
Completed 200 OK in 4007ms (Views: 1222.1ms | ActiveRecord: 2743.8ms)
With Michal's answer, here is a small sample from the log.
Started GET "/comments?lesson_id=370" for ::1 at 2016-09-02 17:13:06 -0400
Processing by Api::CommentsController#index as HTML
Parameters: {"lesson_id"=>"370"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 102]]
Lesson Load (0.4ms) SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = $1 ORDER BY position ASC LIMIT 1 [["id", 370]]
Comment Load (23.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" IS NULL AND "comments"."commentable_type" = 'Lesson' AND "comments"."commentable_id" = 370
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (102)
Comment Load (25.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" IN (38641, 38687, 38733)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (102)
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 38642]]
[active_model_serializers] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 38643]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (30.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 38644]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
My theory is this. I'm convinced the children_comments serialization is causing the majority of the performance problems. Because I have to call children_comments for every comment, this results in a cascading effect. I wonder if I can rewrite the code in a way to improve performance.
You're running into a n+1 queries type problem. Unfortunately includes isn't really helping you here because it only helps you with one level of the association - it avoids separate fetches of the children of the top level comment, but not grand children or great grandchildren.
You could probably optimise the user lookup by maintaining your own cache of user id to user objects (the rails cache caches the raw data but will be reinstantiating the objects over and over again), but to make this substantially faster you need to change how you load the comments.
If you are using a database that supports it (such as postgresql), then recursive queries ar an option (see https://hashrocket.com/blog/posts/recursive-sql-in-activerecord for a worked example). I don't know this scales as the tree gets deeper and deeper.
If recursive queries aren't an option, then there are a few approaches that involve changing what you store.
One is the materialised path patten. For example say that the root comment has id 1, a child has id 101 and one of its children has id 426. That last comment's path is 1/101/426. All of its siblings have paths starting with 1/101/. This means you can use like queries (with wildcards at the end) to find subtrees quickly. The ancestry gem implements this. If comments get moved then you need to rewrite the paths of all the comments children (and grand children etc.), but that may not be relevant to your use case. Very deep trees are problematic I think.
Another is the nested set pattern. The core idea is that the parent node stores the minimum and maximum id of all of its children and their children's children etc. This allows retrieving of all these children in one go. The flip side is that inserts and updates require rewriting a lot of this data (more so than with materialised path). There have been various gems that implement this over the years (a current one seems to be awesome_nested_set).
Also worth checking that you have got the right indexes to support your queries - unless there are really quite a lot of comments with a given parent, 20-30ms seems quite a long time for one query.
Change your ActiveRecord query to this
parent_comments = Comment.where(parent_comment_id: nil).includes(:user, children_comments: :user)
It will get rid of N + 1 queries.

Rails 4 ActiveRecord multiple queries

I use rails 4.2.5.
I have some sort of N+1 problem in this code
seats=SeatItem.where(:b => hall.id).all
seats.each do |seat|
arr << Ticket.new(:a => seat.id)
end
Ticket.import arr
Problem of this code is that i have this in log
MIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE
Why :all method does not load all in memory and how fix it?
Thank you for your input!
I don't think :all is the problem. Notice that the repeated SQL query is identical and that it's fetching rows from seat_item_types not seat_items. My guess is that you have a before/after hook or some other code that is being triggered by Ticket.new or Ticket.import that is accessing seat_item_type.
You should use eager_load for solve N + 1 query problem
use includes method like this
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
But first of all, I think you define associations on SeatItem and Ticket
http://guides.rubyonrails.org/association_basics.html

spree_i18n product filter

I'm having an issue with the spree_I18n gem and the Spree admin panel.
i'm trying to get the admin product filter to work on spree 3.0 stable.
I found this thread : https://github.com/spree-contrib/spree_i18n/pull/602
I changed my gemfile accordingly
This is my gemfile :
gem 'spree', github: 'spree/spree', branch: '3-0-stable'
gem 'spree_gateway', github: 'spree/spree_gateway', branch: '3-0-stable'
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '3-0-stable'
gem 'spree_i18n', git: 'https://github.com/mvz/spree_i18n.git', branch: '3-0-ransack-translations'
I ran bundle install and bundle update spree_i18n but The admin product filter is still returning all of the products. Is there a step that I missed ?
here are the logs :
Started GET "/admin/products?utf8=%E2%9C%93&q%5Bname_cont%5D=Mug&q%5Bvariants_including_master_sku_cont%5D=&q%5Bdeleted_at_null%5D=1" for 127.0.0.1 at 2015-08-26 13:56:39 +0200
Processing by Spree::Admin::ProductsController#index as HTML
Parameters: {"utf8"=>"✓", "q"=>{"name_cont"=>"Mug", "variants_including_master_sku_cont"=>"", "deleted_at_null"=>"1"}}
Spree::User Load (0.2ms) SELECT "spree_users".* FROM "spree_users" WHERE "spree_users"."deleted_at" IS NULL AND "spree_users"."id" = $1 ORDER BY "spree_users"."id" ASC LIMIT 1 [["id", 1]]
(0.3ms) SELECT COUNT(*) FROM "spree_roles" INNER JOIN "spree_roles_users" ON "spree_roles"."id" = "spree_roles_users"."role_id" WHERE "spree_roles_users"."user_id" = $1 AND "spree_roles"."name" = $2 [["user_id", 1], ["name", "admin"]]
(0.4ms) SELECT DISTINCT COUNT(DISTINCT "spree_products"."id") FROM "spree_products" WHERE "spree_products"."deleted_at" IS NULL
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_index_table_options.html.erb (118.4ms)
(0.4ms) SELECT COUNT(DISTINCT count_column) FROM (SELECT DISTINCT "spree_products"."id" AS count_column FROM "spree_products" WHERE "spree_products"."deleted_at" IS NULL LIMIT 10 OFFSET 0) subquery_for_count
Spree::Product Load (0.5ms) SELECT DISTINCT "spree_products".* FROM "spree_products" WHERE "spree_products"."deleted_at" IS NULL ORDER BY "spree_products"."name" ASC LIMIT 10 OFFSET 0
Spree::Variant Load (0.2ms) SELECT "spree_variants".* FROM "spree_variants" WHERE "spree_variants"."deleted_at" IS NULL AND "spree_variants"."is_master" = $1 AND "spree_variants"."product_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) ORDER BY "spree_variants".position ASC [["is_master", "f"]]
Spree::Image Load (0.6ms) SELECT "spree_assets".* FROM "spree_assets" WHERE "spree_assets"."type" IN ('Spree::Image') AND "spree_assets"."viewable_type" = 'Spree::Variant' AND "spree_assets"."viewable_id" IN (17, 18, 19, 20, 21, 22, 23, 24, 25, 26) ORDER BY "spree_assets"."position" ASC
Spree::Variant Load (0.2ms) SELECT "spree_variants".* FROM "spree_variants" WHERE "spree_variants"."deleted_at" IS NULL AND "spree_variants"."is_master" = $1 AND "spree_variants"."product_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) [["is_master", "t"]]
Spree::Image Load (0.4ms) SELECT "spree_assets".* FROM "spree_assets" WHERE "spree_assets"."type" IN ('Spree::Image') AND "spree_assets"."viewable_type" = 'Spree::Variant' AND "spree_assets"."viewable_id" IN (1, 2, 3, 4, 5, 7, 6, 10, 9, 8) ORDER BY "spree_assets"."position" ASC
Spree::Price Load (0.1ms) SELECT "spree_prices".* FROM "spree_prices" WHERE "spree_prices"."deleted_at" IS NULL AND "spree_prices"."currency" = $1 AND "spree_prices"."variant_id" IN (1, 2, 3, 4, 5, 7, 6, 10, 9, 8) [["currency", "USD"]]
Spree::Product::Translation Load (0.1ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 1]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 2]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 3]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 4]]
Spree::Product::Translation Load (0.3ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 5]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 6]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 7]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 8]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 9]]
Spree::Product::Translation Load (0.2ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 10]]
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_index_table_options.html.erb (122.8ms)
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/products/index.html.erb within spree/layouts/admin (370.4ms)
Deface: 1 overrides found for 'spree/admin/shared/_head'
Deface: 'override' matched 1 times with 'title'
Deface: [WARNING] No :original defined for 'override', you should change its definition to include:
:original => 'b94dd9df96e085d9a869128fa811ee3aaf55fab1'
Deface: 1 overrides found for 'spree/admin/shared/_translations'
Deface: 'translation' matched 1 times with 'script'
Deface: [WARNING] No :original defined for 'translation', you should change its definition to include:
:original => '6d879f5c231ff848b4e1023dc0f8b271f922269b'
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_translations.html.erb (27.2ms)
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_head.html.erb (985.0ms)
Deface: 1 overrides found for 'spree/admin/shared/_header'
Deface: 'auth_admin_login_navigation_bar' matched 1 times with '[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]'
Deface: [ERROR] The original source for 'auth_admin_login_navigation_bar' has changed, this override should be reviewed to ensure it's still valid.
CACHE (0.0ms) SELECT COUNT(*) FROM "spree_roles" INNER JOIN "spree_roles_users" ON "spree_roles"."id" = "spree_roles_users"."role_id" WHERE "spree_roles_users"."user_id" = $1 AND "spree_roles"."name" = $2 [["user_id", 1], ["name", "admin"]]
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree_auth_devise-2e8e08759c4d/lib/views/backend/spree/layouts/admin/_login_nav.html.erb (1.2ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_header.html.erb (15.4ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/sub_menu/_product.html.erb (3.3ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/sub_menu/_promotion.html.erb (1.2ms)
Spree::Store Load (0.4ms) SELECT "spree_stores".* FROM "spree_stores" WHERE (url like '%localhost%') ORDER BY "spree_stores"."id" ASC LIMIT 1
Spree::Store Load (0.1ms) SELECT "spree_stores".* FROM "spree_stores" WHERE "spree_stores"."default" = $1 ORDER BY "spree_stores"."id" ASC LIMIT 1 [["default", "t"]]
Spree::Country Load (0.3ms) SELECT "spree_countries".* FROM "spree_countries" WHERE "spree_countries"."id" = $1 LIMIT 1 [["id", 232]]
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/sub_menu/_configuration.html.erb (7.8ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_main_menu.html.erb (106.2ms)
Rendered /Users/stefan/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_content_header.html.erb (0.2ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_alert.html.erb (0.0ms)
Rendered /Users/steven/.rvm/gems/ruby-2.2.1/bundler/gems/spree-a39d06ab644e/backend/app/views/spree/admin/shared/_table_filter.html.erb (0.8ms)
Completed 200 OK in 1711ms (Views: 1697.4ms | ActiveRecord: 6.1ms)

Resources