ruby-on-rails - 两列上的单独索引和 Rails 中对的唯一约束

标签 ruby-on-rails ruby-on-rails-3 postgresql activerecord

我的应用程序使用 PostgreSQL 数据库。我有一个看起来像这样的迁移:

class CreateTagAssignments < ActiveRecord::Migration
  def change
    create_table :tag_assignments do |t|
      t.integer :tag_id
      t.integer :quote_id
      t.integer :user_id

      t.timestamps
    end

    add_index :tag_assignments, :tag_id
    add_index :tag_assignments, :quote_id
  end
end

记录将被这两列频繁搜索,所以我想为每一列创建一个单独的索引。但现在我想在数据库级别强制执行对 (tag_id, quote_id) 的唯一性。我尝试了 add_index :tag_assignments, [:tag_id, :quote_id], unique: true 但我得到了错误:

PG::Error: ERROR:  could not create unique index "index_tag_assignments_on_tag_id_and_quote_id"
DETAIL:  Key (tag_id, quote_id)=(10, 1) is duplicated.
: CREATE UNIQUE INDEX "index_tag_assignments_on_tag_id_and_quote_id" ON "tag_assignments" ("tag_id", "quote_id")

那么多个索引显然可以完成多列索引的工作吗?如果是这样,那么我可以使用 ALTER TABLE ... ADD CONSTRAINT 添加约束,但我如何在 ActiveRecord 中执行此操作?

编辑:手动执行 ALTER TABLE ... ADD CONSTRAINT 会产生相同的错误。

最佳答案

正如 Erwin 指出的那样,“Key (tag_id, quote_id)=(10, 1) is duplicated”约束违反错误消息告诉您现有数据已经​​违反了您的唯一约束。我从您模型的可见性中推断出,不同的用户每个人都可以在标签和报价之间引入共同的关联,因此当您尝试仅限制 quote_id,tag_id 对的唯一性时,您会看到重复项。复合索引对于前导键的索引访问仍然有用(尽管效率略低于单列索引,因为复合索引的键密度较低)。您可能会获得所需的速度以及具有两个索引的适当唯一约束,其中一个 id 上的单列索引和所有三个 id 上的复合索引,另一个 id 作为其前导字段。如果从标签到引号的映射是比从引号到标签的映射更频繁的访问路径,我会试试这个:

add_index :tag_assignments, :tag_id
add_index :tag_assignments, [:quote_id,:tag_id,:user_id], unique: true

如果您使用的是 Pg >= 9.2,则可以利用 9.2 的索引可见性映射来启用对 covering indexes 的仅索引扫描。 .在这种情况下,让上面的第一个索引包含所有三个 id,以 tag_id 和 quote_id 开头可能会有好处:

add_index :tag_assignments, [:tag_id,:quote_id,user_id]

尚不清楚 user_id 如何限制您的查询,因此您可能会发现您还希望索引的位置也提早提升。

关于ruby-on-rails - 两列上的单独索引和 Rails 中对的唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13753551/

相关文章:

ruby-on-rails - 如何将 field_with_errors 类居中

postgresql - 我可以在 SELinux 中使用 .pgpass 吗? [centos7, pgagent_96, postgresql 9.6.5]

sql - Spatialite SQL 查询以查找给定纬度/经度的最近节点

ruby-on-rails - 使用不同的 gemfile 从 Rails 调用 ruby​​ 脚本

ruby-on-rails - 如何将完整的字符串与数字相加?

javascript - rails : flash[:alert] in if-else misbehaving in JQuery

postgresql - PostgreSQL 触发器是异步的吗?

ruby-on-rails - Sidekiq错误: could not connect to server: No such file or directory

ruby-on-rails - Rails 使用博客和帖子构建方法嵌套资源

ruby-on-rails - 错误 : "Unknown validator: ' PresencesValidator'"when trying to validate a form