web-dev-qa-db-ja.com

Railsのテーブルにどのインデックスを追加するか

Railsデータベースについて質問があります。

  • 「xxx_id」などのすべての外部キーに「index」を追加する必要がありますか?
  • 自動的に作成された「id」列に「index」を追加する必要がありますか?
  • 自動的に作成された「id」列に「index(unique)」を追加する必要がありますか?

  • 一度に2つの外部キーにインデックスを追加する場合(add_index (:users, [:category, :state_id])、どうなりますか?これは各キーにインデックスを追加することとどう違うのですか?

    class CreateUsers < ActiveRecord::Migration
      def self.up
        create_table :users do |t|
          t.string :name
          t.integer :category_id 
          t.integer :state_id
          t.string :email
          t.boolean :activated
          t.timestamps
        end
      # Do I need this? Is it meaningless to add the index to the primary key?
      # If so, do I need :unique => true ?
      add_index :users, :id 
      # I don't think I need ":unique => true here", right?
      add_index :users, :category_id # Should I need this?
      add_index :users, :state_id # Should I need this?
      # Are the above the same as the following?
      add_index (:users, [:category, :state_id])
      end
    end
    

これまでの素晴らしい答え。追加の質問。

  • Xxx_idに「一意のインデックス」を追加する必要がありますか?
129
TK.

「xxx_id」などのすべての外部キーに「index」を追加する必要がありますか?

この列での並べ替えで検索が高速化されるため、より良いでしょう。そして、外部キーはたくさん検索されるものです。

Railsのバージョン5以降、インデックスは自動的に作成されます。詳細については、 here を参照してください。

自動的に作成された「id」列に「index」を追加する必要がありますか?

いいえ、これはすでにRailsによって行われています

自動的に作成された「id」列に「index(unique)」を追加する必要がありますか?

いいえ、上記と同じ

一度に2つの外部キーにインデックスを追加する場合(add_index (:users, [:category_id, :state_id])、どうなりますか?これは各キーにインデックスを追加することとどう違うのですか?

その場合、インデックスは2つの列の結合インデックスになります。 1つのcategory_id[〜#〜] and [〜#〜]1つのstate_id(同時にcategoryではなくcategory_idである必要があります。

このようなインデックスは、次のリクエストを高速化します。

# Rails 2
User.find(:all, :conditions => { :state_id => some_id, :category_id => some_other_id })

# Rails 3
User.where(:state_id => some_id, :category_id => some_other_id)

どこで

add_index :users, :category_id
add_index :users, :state_id

これらのリクエストを高速化します:

# Rails 2+3
User.find_by_category_id(some_id)
User.find_by_state_id(some_other_id)

# or
# Rails 2
User.find(:all, :conditions => {:category_id => some_id})
User.find(:all, :conditions => {:state_id => some_other_id})

# Rails 3
User.where(:category_id => some_id)
User.where(:state_id => some_other_id)

Xxx_idに「一意のインデックス」を追加する必要がありますか?

いいえ、これを行うと、1人のユーザーが1つのカテゴリにしか入ることができませんが、カテゴリーの意味は、より多くの多くのユーザーを1つのカテゴリーに入れることができるからです。 Userモデルにはbelongs_to :categoryのようなものがあり、Categoryモデルにはhas_many :usersのようなものがあります。 has_many関係がある場合、foreign_keyフィールドは一意であってはなりません!

詳細については、 tadman の優れた answer をご覧ください。

173
jigfox

インデックス作成は微妙で微妙なことがありますが、どちらを使用するかを簡単に決定できる一般的なルールがあります。

最初に覚えておくべきことは、インデックスは複数の方法で機能することです。 A、B、Cのインデックスは、A、B、および単にAでも機能するため、正しく順序付ければ、より汎用性の高いインデックスを設計できます。電話帳は姓、名で索引付けされているため、姓、または姓と名の組み合わせで簡単に人を検索できます。ただし、名前で直接検索することはできません。そのためには別のインデックスが必要です。同じことが電話番号にも当てはまります。電話番号も同様にインデックス化する必要があります。

それを念頭に置いて、インデックスの作成方法を決定する多くのことがあります。

  • belongs_to-has_many関係のペアリングがある場合は、使用する外部キーのインデックスが必要です。
  • レコードを注文し、ページ分割されるレコードが多数ある場合は、インデックスの最後にその注文列を追加する必要があります。
  • has_many :through関係がある場合、結合テーブルには、複合キーとしての結合に関係する両方のプロパティの一意のインデックスが必要です。
  • ユーザー名や電子メールなどの一意の識別子を使用してレコードを直接取得する場合、一意のインデックスにする必要があります。
  • スコープを使用してhas_many関係からレコードのセットをフェッチする場合、has_many外部キーとスコープ列をこの順序で含むインデックスがあることを確認してください。

インデックスの目標は、データのインデックスが適切に作成されていない場合に発生する恐ろしい「テーブルスキャン」または「ファイルソート」操作を排除することです。

簡単に言えば、アプリケーションによって生成されるクエリを見て、WHEREまたはHAVING条件およびORDER BY句で参照される列がこの順序で表されていることを確認してください。

110
tadman
  • 常に外部キーにインデックスを付ける
  • 常に注文する列にインデックスを付けます
  • すべての一意のフィールド(データベースレベルで一意性を確保するため。移行例:_add_index :users, :email, unique: true_)
  • 2つのことで注文する場合、または2つのことで検索する場合、たとえば_order by [a, b]_またはfind where( a and b )の場合、二重インデックスが必要です。

具体例:

あなたが持っている場合:

_default_scope :order => 'photos.created_at DESC, photos.version DESC'
_

以下を追加する必要があります。

_add_index :photos, [:created_at, :version]
_

注:インデックスはディスク上の余分な領域を占有し、各レコードを再構築する必要があるため、各レコードの作成と更新が遅くなります。

クレジット:

https://tomafro.net/2009/08/using-indexes-in-Rails-choosing-additional-indexesRails-注文するユーザーの場合、created_at、インデックスを追加する必要がありますテーブルに? 、および上記の答え。

10
Will Taylor