Ruby on Rails中多列的索引

时间:2011-05-29 19:42:36

标签: ruby-on-rails ruby-on-rails-3 database-design indexing

我正在实现跟踪用户阅读过哪些文章的功能。

  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表以查找两列,而不仅仅查找一列。我的问题是我的索引应该是什么样子。这些表的顺序是否存在差异,是否应该有更多选项或其他。我的目标数据库是Postgres。

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

感谢。

更新:
因为在两列中只能存在一行包含相同值的行(因为在知道user_id是否读取了article_id时),我应该考虑:unique选项吗?如果我没有弄错,那意味着我不必自己进行任何检查,只需在用户每次访问文章时插入一次。

2 个答案:

答案 0 :(得分:183)

订单在索引方面很重要。

  1. 首先放置最具选择性的字段,即最快缩小行数的字段。
  2. 仅在您从头开始开始使用其列时才使用索引。即,如果您在[:user_id, :article_id]上编入索引,则可以在user_iduser_id AND article_id上执行快速查询,但不能在article_id上执行快速查询。
  3. 您的迁移add_index行应如下所示:

    add_index :user_views, [:user_id, :article_id]
    

    关于'独特'选项的问题

    在Rails中执行此操作的一种简单方法是在模型中使用validates,其范围为uniqueness,如下所示(documentation):

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

答案 1 :(得分:20)

关于检查验证时与索引的唯一性的警告:后者由数据库完成,而引物由模型完成。由于可能同时运行模型的多个并发实例,因此验证受竞争条件的影响,这意味着在某些情况下它可能无法检测到重复(例如,在同一时间提交两次相同的表单)。