在HABTM连接表上需要两个索引?

时间:2013-03-04 20:35:43

标签: ruby-on-rails ruby-on-rails-3 postgresql indexing

一个简单的has_and_belongs_to_many关联:

Person has_and_belongs_to_many :products
Product has_and_belongs_to_many :persons

以下以下索引是否有助于获得最佳效果?

add_index :person_products, [:person_id, :product_id]
add_index :person_products, [:product_id, :person_id]

3 个答案:

答案 0 :(得分:48)

关闭 - 您最有可能想要以下内容:

add_index :person_products, [:person_id, :product_id], :unique => true
add_index :person_products, :product_id

:unique => true并非严格要求,取决于是否有人多次与产品相关联。我会说,如果你不确定,你可能想要:unique标志。

索引结构的原因是所有现代数据库都可以使用第一个索引在person_id和product_id上执行查询,而不管查询中指定的顺序。 E.g。

SELECT foo FROM bar WHERE person_id = 1 AND product_id = 2
SELECT foo FROM bar WHERE product_id = 2 AND person_id = 1

被视为相同,数据库足够智能,可以使用第一个索引。

同样,也可以使用第一个索引运行仅使用person_id的查询。多列b树索引可以使用比原始声明左侧指定的列少的列。

对于仅使用product_id的查询,不能对第一个索引执行此操作(因为该索引是在最左边的位置使用person_id定义的)。因此,您需要一个单独的索引来单独启用该字段的查找。

多列b-tree索引属性还扩展到具有更多列数的索引。如果您在(person_id, product_id, favorite_color, shirt_size)上有索引,则只要订单与定义匹配,就可以使用该索引使用person_id(person_id, product_id)等运行查询。

答案 1 :(得分:3)

是的,他们很有帮助。但你真的需要它们吗?这一切都取决于你将要用它做什么。 (person_id,product_id)上的索引将允许您快速查找属于人的产品,但不会帮助找到拥有某种产品的人。它还将强制执行UNIQUE,因此您可能应该使用它。 (person_id)(product_id)上的单独索引将允许您查找属于个人和拥有特定产品的人的产品。 (person_id,product_id)(product_id,person_id)上的索引也适用于这两种情况,速度会更快,但会占用更多空间,插入/更新行时会占用更多(非常少)。时间和空间开销几乎总是值得的,除非你有一个基础,你写的比阅读更频繁。 就个人而言,我已经看到9.2中的Index Only Scans从两列的两个索引中受益匪浅。 所以你真正的选择是:

unique index on (col 2, col 1), unique index on (col 1, col 2)

unique Index on (col 1, col 2), index on (col 2)

答案 2 :(得分:0)

除非你正在做unique

,否则你只需要一个
add_index :person_products, :person_id
add_index :person_products, :product_id

或两列的索引

add_index :person_products, [:person_id, :product_id]

这将有助于查询数据库上的那些列时的性能。如果它包含两列或只包含一列,它将取决于您的查询。

http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index