web-dev-qa-db-ja.com

Ruby on Railsの複数の列のインデックス

ユーザーが読んだ記事を追跡する機能を実装しています。

  create_table "article", :force => true do |t|
    t.string   "title"
    t.text     "content"
  end

これはこれまでの私の移行です:

create_table :user_views do |t|
  t.integer :user_id
  t.integer :article_id
end

User_viewsテーブルは常に両方の列を検索するためにクエリされ、1つだけではありません。私の質問は、インデックスがどのように見えるかです。これらのテーブルの順序に違いはありますか?私のターゲットDBはPostgresです。

add_index(:user_views, [:article_id, :user_id])

ありがとう。

更新:
両方の列に同じ値を含む行が1つしか存在できないため(user_idがarticle_idを読み取ったかどうかを知るため)、: uniqueオプションを検討する必要がありますか?間違っていなければ、自分でチェックする必要はなく、ユーザーが記事にアクセスするたびに挿入するだけです。

84
Emil Ahlbäck

インデックス付けでは順序が重要です。

  1. 最も選択的なフィールド、つまり、行数を最も速く絞り込むフィールドを最初に置きます。
  2. インデックスは、列を順番に使用する場合にのみ使用されます 初めから。つまり、[:user_id, :article_id]でインデックスを作成する場合、user_idまたはuser_id AND article_idで高速クエリを実行できますが、article_idではできません。

移行add_index行は次のようになります。

add_index :user_views, [:user_id, :article_id]

「ユニーク」オプションに関する質問

Railsでこれを行う簡単な方法は、次のように、スコープがvalidatesのモデルでuniquenessを使用することです( documentation ):

validates :user, uniqueness: { scope: :article }
188
sscirrus

検証時とインデックス時の一意性のチェックに関する警告:後者はデータベースによって行われ、プライマーはモデルによって行われます。モデルの複数の同時インスタンスが同時に実行される可能性があるため、検証は競合状態の影響を受けます。つまり、場合によっては重複の検出に失敗する可能性があります(たとえば、同じフォームを2回同時に送信する)。

21
olivier