便利なherokuと active recordの 速度改善tips
TRANSCRIPT
![Page 1: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/1.jpg)
便利なHerokuとActiveRecordの速度改善Tips
2015-06-06(土) 第9回中国地方DB勉強会 IN 米子株式会社リゾーム システム開発部 尾古 豊明
![Page 2: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/2.jpg)
自己紹介
名前:尾古 豊明
所属:株式会社リゾーム(岡山)
TwitterID:@patorash
鳥取県大山町(旧中山町)出身。
米子東高校卒業後、愛媛大学に進学。松山で就職。
NWしてたけど25歳でPHPプログラマに強制転向。
独自フレームワーク、CakePHP、WordPressなどを経てAndroidやって、1年個人事業主やって、チーム開発がしたくなりリゾームに入社。RubyとRailsを覚える。
DBには詳しくありません!
![Page 3: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/3.jpg)
実家は牧場です
和牛の飼育からお肉の通信販売
焼肉レストランを経営しています
![Page 4: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/4.jpg)
春先から放牧することも
![Page 5: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/5.jpg)
![Page 6: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/6.jpg)
![Page 7: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/7.jpg)
![Page 8: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/8.jpg)
会社の話
![Page 9: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/9.jpg)
とは?
ショッピングセンター(SC)・専門店向けのシステム開発やコンサルティング業務をしている会社です。
Windows系・Java・Rubyなどで自社製品の
開発を行っています。
● 顧客分析システム● デベロッパーマネジメントシステム● BOND GATE(コミュニケーションウェア)● SC GATE(SC・ショップDB)
![Page 10: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/10.jpg)
![Page 11: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/11.jpg)
SC GATEとは?
SCと、そのテナント(ショップ)と運営元の企業を横断的に検索・比較できるデータベースシステムです。
● SCの出店計画を立てるため● 専門店の出店計画● ライバルの動向チェック
などなど。
![Page 12: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/12.jpg)
SC GATEを支える技術
● プログラミング言語 :Ruby 2.2.2● フレームワーク :Rails 4.2.1● プラットフォーム :Heroku● データベース :Postgresql● ソースコード管理 :github● CSSフレームワーク :Bootstrap● AltJS :CoffeeScript● CSS :Sass● テンプレートエンジン :Slim● JSライブラリ :jQuery,Knockout
![Page 13: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/13.jpg)
Ruby on Railsとは?
● 世の中のWebフレームワークで最も大きな影響を与えたであろうMVCフレークワーク
● Railsのようなフレームワークが色んなプログラミング言語で作られた○ PHP・・ CakePHP○ Java・・ SpringMVC、Play Framework○ Python・ Django
● 中でもModelを担当するActiveRecordがものすごく優秀で使いやすい
![Page 14: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/14.jpg)
今日話すこと
● Herokuについて● ActiveRecordについて● PostGISについて
![Page 15: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/15.jpg)
Herokuとは?
● PaaSサービス● 課金でスケーラブルな環境が手に入る● 様々なプログラミング言語をサポート● 様々なデプロイ方法(git, github,DropBox)● 制限が色々…
○ 30秒ルール○ ファイルの保存はできない等
● アドオンを追加することで、拡張可能○ データベース(Postgresql, MySQL)○ SSL○ NewRelicなど監視ツール系、ログ収集系○ メール配信系○ memcachedなどその他色々…
![Page 16: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/16.jpg)
Heroku App
Heroku git
Slug(塊)
Dyno Manager
DynoDyno Dyno
コンパイル
アドオン● データベース● メール配信システム● キャッシュシステム● 状態監視サービス● スケジューラー● SSL● エラー監視サービス● ログサービス
git
Rails
git push heroku tagname:master開発者
● 固有のサーバを持たなくて済む。● Dynoの性能変更でスケールアップ、数を変更でスケールアウト● スポットでDynoの増減をすればいい(イベント時のみ増やすとか)
コード管理はgithubgit push origin develop
![Page 17: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/17.jpg)
Herokuのデータベース
● Heroku Postgresqlが提供されている● MySQLはサードパーティのアドオン● HerokuでRailsアプリを作る場合は
特に制限・こだわりがなければPostgresqlがいいと思う(情報が多いから)
● 定期的にバックアップを取ってくれる● お試しの無料プラン、趣味の$9プラン、
本番環境向けのstandard, premiumなど色々ある。
● 商用だとstandard0以上オススメ($50〜)○ 最大コネクション数が100になるから
![Page 18: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/18.jpg)
ActiveRecordとは?
● 超強力なO/R Mapperです。○ データベースから取得したデータが自動的にクラスのオ
ブジェクトに変換される仕組みのこと
利点● SQLを書かなくてもいい。
● マイグレーションができる。
● データベース周辺を抽象化してくれる。
● オブジェクトなので扱いやすい
欠点
● 遅い(と、よく言われる)
● メモリを大量に使う
![Page 19: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/19.jpg)
利点:SQLを書かなくてもいい
SELECT * FROM articles WHERE id = 1;SELECT * FROM comments WHERE article_id = 1;のようなSQLを書かなくてもよい。結構複雑なところまで網羅できるが、拡張gemを使うとさらに便利に。
article = Article.find 1article.comments.each do |comment| p comment.titleend
![Page 20: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/20.jpg)
ActiveRecordの表現力の高さ
user = User.find 1articles = Article.where(status: ‘open’, user_id: user).order(created_at: :desc).limit(10)
user = User.find 1articles = Article.open.written_by(user).recent(10)
ActiveRecordの流儀に則ってscopeを定義すると、データの絞り込みが流れるように書ける
![Page 21: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/21.jpg)
利点:マイグレーションができる
DB定義の変更はリスクを伴うし、だめだった場合に戻すのが大変だった。しかし、マイグレーションが簡単になったことで気軽にDB定義の変更ができるようになった。
class AddCommentsCountToArticle < ActiveRecord::Migration def up add_column :articles, :comments_count, :integer, default: 0 end
def down remove_column :articles, :comments_count endend
![Page 22: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/22.jpg)
利点:マイグレーションができる
カジュアルにテーブル定義を書き換えられる。
仕様変更しやすい。ダメでもすぐに戻せる。
テーブル定義の変更履歴がマイグレーションファイルとして残るため、
変更の反映漏れが起こる確率はかなり低くなる。
$ bin/rake db:migrate
● テーブル定義を変更する
● テーブル定義を前の状態に戻す
$ bin/rake db:rollback
![Page 23: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/23.jpg)
欠点:遅い(と言われる)
● 適当にコードを書くと、DBアクセス回数が膨大になる(N+1問題)
● 大量のデータを読み込むとメモリを大量に消費する(Rubyでオブジェクトが大量に作られるため)
● Rubyでループを回すと遅い
![Page 24: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/24.jpg)
N+1問題とは?
article = Article.find 1article.comments.each do |comment| p comment.user.nameend
SELECT * FROM articles WHERE id = 1;SELECT * FROM comments WHERE article_id = 1;SELECT * FROM users WHERE user_id = 1;コメントしたユーザー名の取得N回
コメント全件取得1回のDBアクセスが発生する。
![Page 25: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/25.jpg)
どうすれば速くなるか?
● 1度のDBアクセスでデータを取得する(DBアクセス回数を減らす)
● 使うカラムのデータだけ取得する(取得するデータ総量を減らす、 オブジェクトを生成しない等)
● 大量のデータを一度に取得しない(生成するオブジェクトの数を減らす)
● Rubyでのループの回数を減らす(一度に取得する上限は20件まで等)
● そもそもDBにアクセスしない
![Page 26: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/26.jpg)
どうすれば気付くか、減らせるか
● パフォーマンス監視ツールを使う● 検知するためのgemを使う● counter_cacheを使う● 便利なメソッドを使う● ページング用のgemを使う(kaminari)● フラグメントキャッシュを使う
![Page 27: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/27.jpg)
どうすれば気付くか、減らせるか
● パフォーマンス監視ツールを使う● 検知するためのgemを使う● counter_cacheを使う● 便利なメソッドを使う● ページング用のgemを使う(kaminari)● フラグメントキャッシュを使う
![Page 28: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/28.jpg)
New Relic:パフォーマンス監視
![Page 29: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/29.jpg)
![Page 30: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/30.jpg)
NewRelicはローカル環境も見れるhttp://localhost:3000/newrelic/
![Page 31: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/31.jpg)
レスポンスタイムが一目でわかる。遅い場合は赤文字で教えてくれる。そこを速くすればいい。
![Page 32: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/32.jpg)
![Page 33: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/33.jpg)
どんなクエリが発行されて、どれだけ時間がかかっているかが一覧でわかる。遅い場所があれば、そのクエリを改善してみる。結果をキャッシュしてもよいのならキャッシュを試みる。そして、計測する。
![Page 34: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/34.jpg)
bullet:N+1問題検出用gem
![Page 35: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/35.jpg)
N+1問題とは?
article = Article.find 1article.comments.each do |comment| p comment.user.nameend
SELECT * FROM articles WHERE id = 1;SELECT * FROM comments WHERE article_id = 1;SELECT * FROM users WHERE user_id = 1;コメントしたユーザー名の取得N回
コメント全件取得1回のDBアクセスが発生する。
![Page 36: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/36.jpg)
bulletがN+1問題を検出して通知。<= Comment.includes(:user)をすればいいと言ってくれてる。
![Page 37: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/37.jpg)
counter_cacheを使う
関連先のデータ数をキャッシュしておく
例:記事のコメント数がいくらあるか?
SELECT * FROM articles WHERE id = 1SELECT COUNT(*) FROM comments WHERE article_id = 1;2回SQLが実行される
article = Article.find 1article.comments.count
![Page 38: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/38.jpg)
counter_cacheを使う
例:記事のコメント数がいくらあるか?
comments_countカラムを定義して、
更新時にカウント数をキャッシュしておく。
SELECT * FROM articles WHERE id = 1
1回のSQLで済む
article = Article.find 1article.comments_count
![Page 39: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/39.jpg)
![Page 40: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/40.jpg)
counter_cacheの注意点
例えば、論理削除・無効フラグなどを使ってデータを制御している場合は、デフォルトだとその設定は無視される。
絞り込み条件も与えること。
has_many :comments
has_many :comments, -> { where(deleted: false) }
![Page 41: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/41.jpg)
便利なメソッドを使う
Railsは便利だがパフォーマンスが悪い、と
長年言われ続けてきたためパフォーマンス改善のために様々なメソッドが準備されている。
● pluck● find_each● eager_load, joins, preload● to_sql● explain
![Page 42: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/42.jpg)
pluck
モデルオブジェクトを生成せずに指定したカラムの
データを配列で取得する。
titles = Article.pluck(:title)titles.each do |title| puts titleend
articles = Article.allarticles.each do |article| puts article.titleend
![Page 43: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/43.jpg)
find_each
大量のデータを小分けに取得してループする。
一度に大量のオブジェクトが作られないため、
メモリに優しい反面、DBへのアクセス回数は増える
Article.all.each do |article| puts article.titleend
Article.find_each do |article| puts article.titleend
![Page 44: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/44.jpg)
eager_load, joins, preload
関連データをキャッシュしてDBアクセス数を減らす。
代わりにメモリを消費するので大きなテーブル同士は
やめたほうがいい。検索条件に使うだけならjoinsを使う。
article = Article.find 1article.comments.each do |comment| puts comment.contentend
article = Article.eager_load(:comments).find 1article.comments.each do |comment| puts comment.contentend
![Page 45: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/45.jpg)
to_sql
ActiveRecordで組み立てて発行したSQL文を取得する。
サブクエリとして使うパターンもある。
私自身はあまり使わないが、思った通りのデータが取得できないときに、確認のためにデバッグツール上で呼ぶことがある。
query = Article.where(id: 1).to_sql
![Page 46: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/46.jpg)
explain
実行計画を見ることができる。
私自身は全く使ったことがない。
Article.where(id: 1).explain
![Page 47: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/47.jpg)
PostGISについて
PostGISはGISを扱うための拡張機能
GeographicInformationSystem・・・ 地理情報システム
緯度・経度・標高など
平たくいうと、Google Mapsなど地図アプリで独自
のデータを扱う際などに便利!
![Page 48: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/48.jpg)
PostGISのなにが嬉しいのか?
位置情報からレコードを
検索できる
例えば・・・
● 指定した緯度・経度から
半径10km以内のレコードを取得
● 距離でソートなど
![Page 49: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/49.jpg)
![Page 50: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/50.jpg)
![Page 51: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/51.jpg)
ActiveRecordでPostGIS
● activerecord_postgis_adapterを利用することで使える
● 2系だとRails4.2系がサポートされていなかった。スライド書き始めた時は最新が3.0.0.β5だったが、最近3.0.0がリリース
![Page 52: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/52.jpg)
GISを扱う時にハマッたポイント
測地系:世界測地系・日本測地系
● 数百メートル近くずれる● activerecord_postgis_adapterでは、
世界測地系しかサポートしていない● システム的には、日本測地系のデータしか使わ
ない● 毎回、測地系変換をJS側で実行している
![Page 53: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/53.jpg)
HerokuでPostGISは使えるか?
使える
● PostGISの有効化● Rails起動時にAdapter差し替え処理を追加
○ Herokuのドキュメントに書いてある
※ただし、正式サポートではない
![Page 54: 便利なHerokuと active recordの 速度改善tips](https://reader034.vdocuments.net/reader034/viewer/2022042514/55ba0e12bb61eb8d158b4633/html5/thumbnails/54.jpg)
以上!!