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

20200704_出張_Railsウォッチ_in_銀座Rails_23

 20200704_出張_Railsウォッチ_in_銀座Rails_23

2020/07/04に銀座Rails#23で発表したスライドです。
https://ginza-rails.connpass.com/event/178203/
週刊Railsウォッチ: https://techracho.bpsinc.jp/tag/%e9%80%b1%e5%88%8arails%e3%82%a6%e3%82%a9%e3%83%83%e3%83%81

37b01da9150c1e789f35771b06d36890?s=128

Masato Mori

July 04, 2020
Tweet

Transcript

  1. 出張!Railsウォッチ
 in 銀座Rails#23
 森 雅智 / @morimorihoge 1
 特集:~ActiveRecordのSELECTベンチマーク~


  2. About Me
 • 森 雅智: @morimorihoge
 • BPS株式会社でRailsの受託開発チームをやってたり、週1大学非常勤で Web開発を教えてたりします
 •

    Ruby/Rails歴は11年くらい。Web開発は17年くらい
 • 銀座Ralis #10でActiveRecordでVIEWを使おうという話をしました
 About BPS & TechRacho
 • Web受託開発や電子書籍製品開発をやっている会社です
 • TechRachoという自社技術Blogを運営しています
 ◦ 3年半ほど前から平日毎日更新してます
 ◦ https://techracho.bpsinc.jp/ • お仕事相談、転職相談、TechRachoへのご意見など気軽にどうぞ
 ◦ https://www.bpsinc.jp/ 2

  3. Railsウォッチとは?
 技術ブログTechRachoで毎週連載しているRails / Ruby界隈を中 心とした雑多な情報を提供する技術雑談マガジン
 3


  4. これまでの出張Railsウォッチのピックアップテーマ
 • Rails6新機能特集
 ◦ 銀座Rails#12: 複数DB対応
 ◦ 銀座Rails#13: ActionText、Trix
 ◦

    銀座Rails#14: ActionMailbox
 • Railsアプリケーション開発に関する雑多なテーマ
 ◦ 銀座Rails#15: production、development、staging環境について
 ◦ 銀座Rails#16: 機能開発の設計レビューについて
 ◦ 銀座Rails#17: リソース管理スコープについて
 • 開発一般な話
 ◦ 銀座Rails#19: 開発チームの冗長化について
 ◦ 銀座Rails#20: Excelと仲良くしよう
 ◦ 銀座Rails#21: 標準仕様を読むためのABNF
 ◦ 銀座Rails#22: CLIプログラムにOptionParserを使う
 4
 ※過去のスライドはTechRachoにて公開しています。「TechRacho 銀座Rails」あたりで 検索するとヒットしますので興味のある方はどうぞ

  5. ActiveRecordのSELECTベンチマーク
 5


  6. 話のきっかけ
 • 以前やたらと遅いActiveRecordの#each処理を#selectでSELECTするカラムを絞り 込んだら高速化できた、という話をふと思い出した
 • 当時は試行錯誤の中フィーリングで試した高速化施策の一つだったが、ちゃんと調 べてみようと思い立った
 ◦ Railsのベンチマークをきちんとやってみようという気持ち 


    ◦ フィーリングではなく定量的に計測してみることで高速化方法に根拠を持てるようになる 
 6
 本発表で使った動作環境
 • Hyper-V上のManjaro(Arch Linux系)環境
 • ruby 2.7.1p83(rbenv)
 • Rails 6.0.3.1
 • PostgreSQL 12.3(Docker Container、同一VM上)

  7. Railsコードのベンチマーク方法について
 • Rails Guidesの「Ruby on Rails に貢献する方法」の項でbenchmark-ips gemにつ いて触れられている。
 •

    今回はメモリ使用量についても計測したかったため、benchmark-memory gemも 併用した
 7
 https://railsguides.jp/contributing_to_ruby_on_rails.html#%E3%83%99%E3%83%B3%E3%83%81%E3%83%9E %E3%83%BC%E3%82%AF%E3%82%92%E8%A1%8C%E3%81%86

  8. 実際のベンチマーク方法
 • Rails Guidesから参照されているテンプレートを以下のように改変し、rails runner経 由で呼び出すことで動かす
 ◦ Rails一式が読み込まれる分起動が遅いが、その分既存アプリのModelなども全部読み込まれるの でアプリケーションベンチマークとしては使いやすい(私見です) 


    8

  9. ActiveRecordの発行するSELECT文について
 • ActiveRecordはデフォルトでSELECT *なSQLを発行することが知られている
 
 
 • 特定のカラムのみ取得したければActiveRecord#selectを使えば良い
 
 


    • #pluck などはSELECT *しない実装になっている(ので早い)
 9

  10. なぜSELECT *したくないのか
 10
 仮説1
 SELECT結果が大きいとデータサイズが大き くなる分転送に時間がかかるはず 
 仮説2
 ARオブジェクトを作る際、カラムが多ければ よりメモリやCPUを消費しているはず

    
 ※今回のベンチマークではRDB(PostgreSQL)は同一VM上のDocker Containerで実行しているため、仮 説1の差は有意に出ない可能性あり 

  11. 検証準備
 • 以下のようなusersテーブルを作成(極端なケース)
 ◦ 20個のintegerカラム 
 ◦ 20個のvarchar(string)カラム 
 ◦

    20個のtextカラム
 • 作成したusersテーブルのデータをやりくりしつつベンチマークを取っていく
 11

  12. #selectありなしで有意差はあるかを確認
 • 1000件でeach&カラムを一つ参照してみて計測
 12
 SELECTすると3.8倍高速 
 SELECTすると1/7程度のメモリ消費 
 ※極端なケースでテストしているので鵜呑みにし過ぎないように注意 


  13. #selectするカラム数でどの程度変化するか?(1)
 • 1000件でeach&カラムを参照してみて計測
 13
 (以下略)
 ※生データだと分かりにくいので次ページチャートへ


  14. #selectするカラム数でどの程度変化するか?(2)
 14
 x: #selectしたカラム数
 y: instruction/sec(大きければ高速)


  15. #selectするカラム数でどの程度変化するか?(3)
 15
 x: #selectしたカラム数
 y: memsize(kb)


  16. メンバ参照の有無による差はあるか?(1)
 #each内でselectしたカラムを参照するかどうかでlazy load度合いが変わる気がしたので 計測してみた。
 ※使わないカラムをSELECTしても参照しなければそこまで悪影響がないかもしれない 仮説
 16


  17. メンバ参照の有無による差はあるか?(2)
 17
 x: #selectしたカラム数


  18. さらなる検証の余地
 • integer以外の型について、どの程度メモリ使用量に差異が出るのか?(varcharや text型などの可変データはどうなる?)
 • integer以外のRubyオブジェクトに変換するのが重そうな型の場合、さらに実行速度 に有意な差が出るかもしれない(JSONやtimestamp型など)
 • 最近 @kamipo

    さんがimmutable_strings_by_defaultやLazyAttributeHash 周りの更新をmasterに入れているので、メンバ参照しないケースはRails 6.0.4 or 6.1.0では劇的に早くなる気がする
 ◦ https://github.com/rails/rails/pull/39599
 ◦ https://github.com/rails/rails/pull/39612
 18

  19. まとめ
 • ActiveRecordで#selectによるカラム絞り込みの効果を計測した
 • カラム絞り込みの有無により、メモリ使用量削減だけでなく実行速度にも有意な差 異が見られることが分かった
 • まだまだ試してみたいシナリオはあるので、好評そうならまた追加で調べてまとめ たいと思います
 19


  20. 次回以降もブラッシュアップしていきます
 感想・リクエストなどあればTwitter
 #ginzarails
 @morimorihoge
 @hachi8833
 までお声かけください
 20