一から勉強させてください( ̄ω ̄;)

最下級エンジニアが日々の学びをアウトプットしていくだけのブログです。

シーケンシャルスキャンとインデックススキャンを意識して生きていきたい

最近RailsでツラいクエリをRDBに投げまくって失敗してしまったのでメモ。

例えばusersテーブルがあって、一部のAwesomeなユーザーだけにawesometrueで割り当てられている(基本false)とする。そしてawesomeカラムにはインデックスが貼られているとする。

そして

class User < ActiveRecord::Base
  scope :awesome, -> { where awesome: true }
  scope :normal, -> { where awesome: false }
end

とする。

ここで、ユーザーレコードが100万件あってそのうち100件だけがAwesomeだった場合を考えたい。

# これは100万件から100件を探して取ってくるのでインデックス最高ってなる
User.awesome

# これは100万件から99万9900件を探して取ってくるので地獄度が高い
User.normal 

インデックスを貼ったからと安心して何も考えずにRDBからデータを引っ張ってはいけない。これはユーザー100万件をシーケンシャルスキャンするのとなんら変わらんではないか。むしろはじめにインデックスを読んでからシーケンシャルスキャン同等の検索をしている分タチが悪い可能性もある。

こちらの記事を参考にさせてもらったけど、インデックススキャンは大量検索には向かない。シーケンシャルスキャンとの特性を比較した図も載っていてわかりやすかった。

まとめ

N+1には普段から気をつけていたけど、それ以外にも非効率なクエリをつい投げてしまっていることがあるなと実感した。Railsなど便利なフレームワークを使っていたとしても、非効率なクエリを投げてしまっていないか、ログなどを見つつ常に意識していきたい。

参考