16

Я столкнулся с конкретной ситуацией, когда рендеринг json, созданный ActiveModel :: Serializer, необычайно медленный (около 6-8 секунд). Как я могу улучшить скорость этого рендеринга? Вот код.Active Serializer - увеличение производительности рендера

Модель:

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 

сериализаторов:

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 

В моем контроллере у меня есть

parent_comments = Comment.where(parent_comment_id: nil) 

    render status: :ok, 
     json: parent_comments, 
     each_serializer: CommentSerializer, 
     key_transform: :camel_lower 

Вот мой частичный выход журнала, когда я делаю вызов к серверу. Как вы видите, Active Serializer занимает около 20 мс, чтобы сделать каждый запрос.

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) 

С ответом Михала, вот небольшой образец из журнала.

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]] 

Моя теория такова. Я убежден, что сериализация children_comments вызывает большинство проблем с производительностью. Поскольку я должен вызывать children_comments для каждого комментария, это приводит к каскадному эффекту. Интересно, могу ли я переписать код таким образом, чтобы повысить производительность.

+0

Вы используете драгоценный камень oj? – DVG

+0

Да, жемчужина oj не показывает никакой разницы в производительности. – jason328

+0

Пробовали ли вы прокомментировать это? С ruby-prof или stackprof? Он расскажет, какая часть на самом деле медленная. –

ответ

5

Изменить запрос ActiveRecord к этому

parent_comments = Comment.where(parent_comment_id: nil).includes(:user, children_comments: :user) 

Он будет избавиться от N + 1 запросов.

+0

К сожалению, это не улучшило время. Время загрузки комментариев было примерно одинаковым. – jason328

+0

@ jason328 И как выглядит вывод журнала? –

+0

отправил в вопрос. – jason328

3

Вы столкнулись с проблемой типа n + 1 запросов. К сожалению, includes на самом деле не помогает вам здесь, потому что он помогает вам только на одном уровне ассоциации - он позволяет избежать отдельных выписок детей из комментариев верхнего уровня, но не внуков и правнуков.

Возможно, вы можете оптимизировать поиск пользователей, сохранив свой собственный кеш идентификатора пользователя для объектов пользователя (кеш рельсов кэширует необработанные данные, но будет снова и снова восстанавливать объекты), но чтобы сделать это значительно быстрее, вам нужно чтобы изменить способ загрузки комментариев.

Если вы используете базу данных, которая ее поддерживает (например, postgresql), тогда рекурсивные запросы являются опцией (см. https://hashrocket.com/blog/posts/recursive-sql-in-activerecord для обработанного примера). Я не знаю этих масштабов, когда дерево становится все глубже и глубже.

Если рекурсивные запросы не являются опцией, есть несколько подходов, которые включают изменение того, что вы храните.

Первый - материализованный путь patten. Например, скажем, что корневой комментарий имеет id 1, у ребенка есть идентификатор 101, а один из его дочерних элементов имеет id 426. Этот путь последнего комментария - 1/101/426. У всех его братьев и сестер есть пути, начинающиеся с 1/101/. Это означает, что вы можете использовать подобные запросы (с подстановочными знаками в конце), чтобы быстро найти поддеревья. Этот камень использует драгоценный камень ancestry. Если комментарии перемещаются, вам необходимо переписать пути всех комментариев детей (и внуков и т. Д.), Но это может не иметь отношения к вашему варианту использования. Думаю, очень глубокие деревья проблематичны.

Другой - это шаблон вложенного набора. Основная идея заключается в том, что родительский узел хранит минимальный и максимальный идентификатор всех своих детей и детей своих детей и т. Д. Это позволяет получить всех этих детей за один раз.Оборотная сторона заключается в том, что вставки и обновления требуют перезаписи многих этих данных (более того, чем с материализованным путем). Там были различные драгоценные камни, которые реализуют это на протяжении многих лет (текущий, кажется, awesome_nested_set).

Также стоит проверить, что у вас есть нужные индексы для поддержки ваших запросов - если нет достаточного количества комментариев с данным родителем, 20-30 мс кажется довольно длинным для одного запроса.

+0

Вы дали наиболее исчерпывающий ответ с несколькими возможными решениями. Для этого я дам вам кредит. Спасибо за обширный ответ. – jason328