Rails: 闇雲にインデックスを付けてはいけない(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Rails: 闇雲にインデックスを付けてはいけない(翻訳)

最近、使われてないインデックスを外す作業を行ってたのですが、やってみると出るわ出るわ。そのほとんどは、逆関連付けの不要なモデルのJOINの一部でした。次の例で考えてみましょう。

class ShoppingCart < ActiveRecord::Base
  has_many :shopping_cart_products
  has_many :products, through: :shopping_cart_products
end

class ShoppingCartProduct < ActiveRecord::Base
  belongs_to :shopping_cart
  belongs_to :product
end

class Product < ActiveRecord::Base
end

商品を含むショッピングカートとしてはごく普通の設計です。

このShoppingCartProductモデルはRailsのモデルジェネレータで作成されました。このとき、マイグレーションの他に関連付けを含むモデルクラスが作成されました。

$ bin/rails g model CartProduct quantity:integer{1} user:belongs_to product:belongs_to --no-test-framework
class CreateShoppingCartProducts < ActiveRecord::Migration
  def change
    create_table :shopping_cart_products do |t|
      t.integer :quantity, limit: 1, null: false
      t.belongs_to :shopping_cart, index: true, foreign_key: true
      t.belongs_to :product, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end

適切な処置として、このquantityカラムはnull値を許さないよう設定されていました。このとき、shopping_cart_productsに2つのインデックスがデフォルトで作成されていたことにご注目ください。

実際には、このインデックスはショッピングカートに特定の商品を含むショッピングカートを表示するうえでほとんど意味がありません。つまり、product_idごとにShoppingCartProductのクエリをかける必要などないので、このインデックスは使われていませんでした。Railsが生成するモデルやマイグレーションに、このインデックスが息を殺して潜んでいたのです。

使われてないインデックスは、データベースリソースの無駄使いです。ストレージ容量を消費し、UPDATEINSERTの速度も落ちます。このときはshopping_cart_productsがそうでした。

使われていないインデックスを取り除くのは簡単です。

class RemoveIndexShoppingCartProductsOnProductId < ActiveRecord::Migration
  def up
    remove_index(:shopping_cart_products, :product_id)
  end

  def down
    add_index(:shopping_cart_products, :product_id)
  end
end

データベースにインデックスを追加するときは、よく考えてからにしましょう。本当に必要であることを確認できてから追加すべきです。

アプリの要件は時とともに変わりますので、そのうちインデックスが必要になるかもしれません。使われてない可能性のあるインデックスを検出するために、データベースツールで定期的に監視しましょう。production環境でも最良の結果を得るためにこの点を監視しておきましょう。

関連記事

PostgreSQLデータベースで「トップN」集計をうまく扱うTopN extension(翻訳)

Rails tips: 遅いクエリのログをDB設定変更なしで取るコツ(翻訳)

pgloader 3.4.1でMySQLからPostgreSQLへスマートに移行しよう(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ