![見出し画像](https://assets.st-note.com/production/uploads/images/63216716/rectangle_large_type_2_1d56b3c0f9450c5aa93c43aaddcdbce5.png?width=800)
railsのデータ取得速度を改善する
今回の記事は自身の作成しているアプリの改善日記みたいなものです。
rails によく起こるN+1問題はgemのbulletをいれてある程度は解消しました。
しかしながら大量のデータを扱ったことがないので、大量のseedデータを投入して速度を早くしていこうと思います。
とりあえずは一人のpostが1000件ずつにしていきます。
まずは全体投稿のページですが、
こちらはデータが何件に増えようとも問題なく表示されています。
kaminari とinifinity loading を導入していたので取得するデータが限られます。
そのためデータ件数は関係ないという感じです。
しかしながら
usershowページは
表示もされません。
これはここにpagenationとinfinity loadingを導入していないからです。今後導入していきます。
しかしながら、今回はSQLのデータを整形して取得するデータを速くしてみようと思います。
速くしてみたいので!
それではやっていきます。
http://localhost:3000/api/v1/users/4
にアクセスすると
この様なログが走っていました。
なぜか[active_model_serializers]が無駄に走っています。
まずこれを消しましょう。
原因はjsonでデータを受け渡すときにuserという名前で受け渡すと自動でシリアライザーを通る設定がなされているためでした。
変更前 render json: @user
変更後 render json: @user.as_json
これで余計なSQLがはしらなくなりました。
一つの投稿についても速くしてみましょう
http://localhost:3000/api/v1/posts/1
これがpostsのshowアクションで取れるデータです
def show
post = {}
post[:post] = Post.includes([:user]).find(params[:id])
post[:user] = User.find(post[:post].user_id)
post[:comments] = Post.joins(:user).select("posts.*, user AS user").where(post_id: params[:id]).order(created_at: :desc)
post[:like_posts] = LikePost.where(post_id: params[:id]).order(created_at: :desc)
post[:like_count] = post[:like_posts].length
unless post.nil?
render json: post.as_json
else
render json: { error_message: 'Not Found' }
end
end
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (1.08ms)
api_1 | Completed 200 OK in 110ms (Views: 2.0ms | ActiveRecord: 15.5ms | Allocations: 33691)
これを変更していきます。
def show
post = {}
post[:post] = Post.joins(:user).find(params[:id])
# 先に内部結合し二行目で内部結合したデータを表示
post[:user] = post[:post].user
post[:comments] = Post.select(:id).where(post_id: params[:id]).order(created_at: :desc)
# 必要なデータはidだけだったのでselectで必要最低限にする
post[:like_posts] = LikePost.where(post_id: params[:id]).order(created_at: :desc)
post[:like_count] = post[:like_posts].length
unless post.nil?
render json: post.as_json
else
render json: { error_message: 'Not Found' }
end
end
api_1 | [active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.39ms)
api_1 | Completed 200 OK in 17ms (Views: 0.9ms | ActiveRecord: 2.9ms | Allocations: 4657)
変更前
→ Completed 200 OK in 110ms (Views: 2.0ms | ActiveRecord: 15.5ms | Allocations: 33691)
変更後
→ Completed 200 OK in 17ms (Views: 0.9ms | ActiveRecord: 2.9ms | Allocations: 4657)
これでだいぶ早くなりました。
activerecordで取得したいデータを最低限にすることでデータ取得速度が早くできるので、次回からは設計段階から必要最低限のデータは何かを考えながら作っていきたいなと思います。
この記事が気に入ったらサポートをしてみませんか?