2013-03-04 61 views
25

一个简单的has_and_belongs_to_many协会:在HABTM连接表上需要两个索引?

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] 

回答

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

+3

我的理解是,如果查询是通过'product_id'然后'person_id'进行的,它不会使用上面两个列中的索引。 – sscirrus 2013-03-04 20:47:04

1

是的,他们是有帮助的。但是你真的需要他们吗?这完全取决于你要怎么做。 (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)

38

关闭 - 你很可能希望以下内容:

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

:unique => true并不严格要求这取决于是否有一个人相关联是有意义的用产品多次编辑。我会说如果你不确定,你可能想要:unique标志。

索引结构的原因是,无论查询中指定的顺序如何,所有现代数据库都可以使用第一索引对person_id和product_id执行查询。例如。

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-tree索引可以使用比它们在原始声明左侧指定的更少的列。

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

多列b-tree索引属性也延伸到具有更多列数的索引。如果您有(person_id, product_id, favorite_color, shirt_size)索引,那么只要顺序与定义匹配,就可以使用该索引来运行person_id,(person_id, product_id)等查询。