Logo
  • DoRubyとは
  • お問い合わせ
  • Ruby/Rails
  • Web開発
  • Webマーケティング
  • アピリッツ
  • ライフハック
  • ゲーム制作/開発
  • アプリ開発
  • 新しいカテゴリ
  • Railsの小技
  • Rubyの小技
  • Gemの紹介
  • ActiveRecord
  • 初心者向け
  • Java/Scalaテク
  • Unixのあれこれ
  • データベース
  • スマホ開発
  • HTML/CSS/JavaScript
  • デザイン製作
  • インフラ
  • クラウド
  • セキュリティ
  • エディタ
  • バージョン管理
  • その他
  • python
  • アクセス解析
  • Googleアナリティクス
  • Googleデータスタジオ
  • Web広告
  • SEO
  • UI/UX
  • ソーシャルメディア
  • EC開発
  • Webシステム開発
  • コンサルティング
  • Webデザイン
  • ブロックチェーン
  • ゲーム紹介
  • アプリ紹介
  • ASP
  • 風景
  • パソコン
  • ツール
  • ガジェット
  • 仕事術
  • 健康
  • 生活
  • 書評
  • Excel(エクセル)
  • PowerPoint(パワーポイント)
  • ゲームプランニング
  • SpriteStudio
  • マスターデータ入力/作成
  • Unity
  • キャラクターデザイン
  • ゲームシナリオ
  • レベルデザイン
  • ゲーム分析
  • 3DCG
  • イラスト制作
  • CG/アニメーション
      1. ホーム
      2. Ruby/Rails
      3. ActiveRecord
      4. ActiveRecord::Relationの落とし穴:解決編
      • 2017-07-03
        • カテゴリ:
        • ActiveRecord
        • タグ:
        • ActiveRecord
        • Rails
        • ruby

      ActiveRecord::Relationの落とし穴:解決編

      D401d7ad39c10286ef030fd8d5c00f51

       職場に浅草観光で買った食品サンプルを持ってきて、何も言われないのにホッとしながらも残念にも思っていたら、暫くして上長に初めて聞かれて6800円の値段に驚かれたHelloWorld!?です。
       前回の記事で、ActiveRecord::Relationに関して書きましたが(ActiveRecord::Relationの落とし穴)、上辺しか見る事が出来ていなかった、原因はもっと別の場所にあった、という事が、先輩社員や同期からの指摘で分かりました。それから自分なりに色々調べた結果、理解が深められたので、それに関して書こうと思います。

      本題:ActiveRecord whereメソッド

       まず、焦点となったActiveRecord::Relation、を返すwhereメソッドに関して、その周辺も含めるソースコードを見てみました。
      rails/activerecord/lib/active_record/relation/query_methods.rb

          def where(opts = :chain, *rest)
            if :chain == opts
              WhereChain.new(spawn)
            elsif opts.blank?
              self
            else
              spawn.where!(opts, *rest)
            end
          end
      
          def where!(opts, *rest) # :nodoc:
            opts = sanitize_forbidden_attributes(opts)
            references!(PredicateBuilder.references(opts)) if Hash === opts
            self.where_clause += where_clause_factory.build(opts, rest)
            self
          end
      

       ......これだけ見ても、何してるのか全く分からないです。少なくとも、ここ辺りのコードを見た事が無い自分にとっては。
       とりあえず、このコードを色々調べてみて、自分なりの擬似コードにしてみました。

          def where(条件、プレースホルダの値)
            if 引数が無かったら
              WhereChainの新しいインスタンスを返す
              #WhereChain : 条件がなかった時に、プレースホルダとして働くもの
            elsif 条件が空だったら
              自身を返す
            else
              where!(条件、プレースホルダの値)を呼ぶ
            end
          end
      
          def where!(条件、プレースホルダの値)
            条件の属性を確かめる
            条件がハッシュで構成されたものならば、文字列へ加工を施す
            条件を付け加える
          end
      

       という感じでした。
       そしてその加えられた条件は、最終的に値を取り出そうとする時にbound_attributesが呼ばれることによってSQLに代入され、レコードが取り出される、という過程を踏みます。
       自分が前回の記事で間違えた点は、その記事にも書き加えましたが、whereを呼んだだけでは条件が追加されるだけで、ActiveRecord::Relationに実際に値は入らないという事です。
       なので、それで最初から要素を入れたい時は、where(...)と呼ぶのではなくその後にloadなり適当な値を取り出すメソッドなりを呼んであげる必要がある、という事でした(where(...).loadとか)。loadをしなくとも、最終的な計測時間は変わらない訳なのですが、そこで自分は勘違いして、変な計測結果を出していたりした訳です。
       後、計測時間を、Load有りと無しでまた測ってみました。(railsコンソール上で計測)
       横軸:レコード数
       縦軸:経過時間(秒)
      enter image description here
      enter image description here
       ロード有りだと、ほぼほぼ時間は変わらない結果になりました。
       ただ、無しだと結構差が出ているので、ロードしてから何度も走査したりする必要があるのならば、ハッシュや配列の形式にして出力した方が良いかもしれません。

       そして、そこからもう一つ、疑問が浮かびました。
       前回の記事では、hashなどに形式を変換したら、劇的に動作速度が向上した、と書きました。実際その通りだったのですが、上記の結果を鑑みると、Load有りでは、ほぼほぼ時間は変わりませんし、Load無しにしたとしても、よほど走査を繰り返さない限り、目に見える程の差は出ないはずです。
       なら、何故......?
       と思ってその遅いコードを眺めてみようと思ったら、commitしていなかったのでもうありませんでした。
       ......。
       でも推測として、多分SQLの呼び出しを一回のループの中で複数やるようなコードを書いてしまっていたのではないか、という事が理由なのではないか、と思っています。それ以外で余り劇的な動作速度の向上が起こるような原因も思い当たりませんし。また、データを色々こねくりまわしていた所もありましたので。(またcommitに対しても、出来たコードがおかしなコードでも、キリのいいところならばコミットするようにします。過去の自分がどのように実装したか、また、他人が見た時にもcommitが小まめにされていれば、そのコーディングの軌跡が分かり易いですし。)

      結論

       whereを呼んで新しく作成されるものは、SQLの条件であり、データ本体では無い。SQLを呼んでデータをロードする為には、何かしらこちらから手を加えないといけない(それに関しては、こちらの記事に詳しく書いてあります:ActiveRecord::Relationとは一体なんなのか)。
       特に、ボトルネックを調べる場合など、それが原因で混乱する可能性がある。


      • 133 views
        • Tweet
        • このエントリーをはてなブックマークに追加

      この記事を書いた人
      F7eb52677a0e9796e154969ea5171e15?default=mm&size=80
      HelloWorld?
      ズボラなのにケーキを作って成功したプログラマ

      「いいね!」するとDoRubyの最新記事を受け取ることができます。

      Facebook

      Twitterから最新記事を受け取るならこちら

      Follow @doruby

      Feedlyから最新記事を受け取るならこちら

      follow us in feedly

      おすすめの記事
      • 345 views
      • 2015-10-01
      RailsのViewを自在にカスタマイズするための「Cosme」gem
      • 1,273 views
      • 2016-07-27
      リニューアルをしたDoRubyの3つの目的
      • 601 views
      • 2016-07-31
      carrierwaveとfogでRiak CSへの画像アップロードを実装する
      • 696 views
      • 2017-04-24
      アピリッツの新卒合宿2017

      カテゴリ

      Icon category 1Ruby/RailsList elementRailsの小技List elementRubyの小技List elementGemの紹介List elementActiveRecordList element初心者向けIcon category 4Web開発List elementJava/ScalaテクList elementUnixのあれこれList elementデータベースList elementスマホ開発List elementHTML/CSS/JavaScriptList elementデザイン製作List elementインフラList elementクラウドList elementセキュリティList elementエディタList elementバージョン管理List elementその他List elementpythonIcon category 5WebマーケティングList elementアクセス解析List elementGoogleアナリティクスList elementGoogleデータスタジオList elementWeb広告List elementSEOList elementUI/UXList elementソーシャルメディアIcon category 6アピリッツList elementEC開発List elementWebシステム開発List elementコンサルティングList elementWebデザインList elementブロックチェーンList elementゲーム紹介List elementアプリ紹介List elementASPList element風景Icon category 7ライフハックList elementパソコンList elementツールList elementガジェットList element仕事術List element健康List element生活List element書評List elementExcel(エクセル)List elementPowerPoint(パワーポイント)List elementゲーム制作/開発List elementゲームプランニングList elementSpriteStudioList elementマスターデータ入力/作成List elementUnityList elementキャラクターデザインList elementゲームシナリオList elementレベルデザインList elementゲーム分析List element3DCGList elementイラスト制作List elementCG/アニメーションList elementアプリ開発List element新しいカテゴリ

        人気の記事
        • 110 views
        • 2018-03-30
        極・メカニカルキーボード生活
        • 78 views
        • 2018-04-02
        メモ化トラップ
        • 73 views
        • 2018-03-23
        協力要素のあるゲームにおける初心者について考える
        • 57 views
        • 2018-03-26
        よくわからないで使っている英語の意味を知っとこう
        • 55 views
        • 2018-03-28
        Ruby×PyCallでTensorflowのMNISTチュートリアル
        最近の記事
        • 48 views
        • 2018-04-02
        心くすぐられる物理学ワード
        • 50 views
        • 2018-04-02
        花粉症を軽減する方法
        • 78 views
        • 2018-04-02
        メモ化トラップ
        • 33 views
        • 2018-04-02
        Unityのシェーダーについて
        • 38 views
        • 2018-03-30
        iOS/Android向けアプリの審査基準
        Facebook

          サイト情報
          • DoRubyとは
          • 株式会社アピリッツ

          企業情報
          • 会社概要
          • 採用情報
          • お問い合わせ

          ソーシャルアカウント
          • Facebook
          • Twitter
          サービス製品
          • コミュニティサイト
          • Android向け ECアプリ制作パッケージ「ポケコマ」
          • レコメンドASP
          • サイト内検索ASP「Advantage Search」
          • オープンソースECサイト構築パッケージ「エレコマ」

          • 受注・在庫・商品情報一元管理「モールコネクター」
          • セキュリティ診断サービス
          • 戦略的EC画面設計・制作サービス
          • Googleアナリティクスセミナー
          • アクセス解析コンサルティング
          • SEOコンサルティング

          Copyright © Appirits All Rights Reserved.