ActiveRecord中多列的索引

时间:2009-06-26 12:36:42

标签: sql ruby-on-rails activerecord indexing

在ActiveRecord中,有两种方法可以为多列声明索引:

add_index :classifications, [:species, :family, :trivial_names]
add_index :classifications, :species
add_index :classifications, :family
add_index :classifications, :trivial_names

第一种方法和第二种方法之间有什么区别吗?如果是这样,我何时应该使用第一个和第二个?

3 个答案:

答案 0 :(得分:89)

您正在将复合索引与一组独立索引进行比较。他们只是不同。

以这种方式思考:复合索引使您可以快速查找嵌套字段集中的第一个字段,然后快速查找第二个字段仅在第一个字段中已经选择的记录字段,然后快速查找第三个字段 - 再次,仅在前两个索引选择的记录中。

让我们举个例子。您的数据库引擎将花费不超过20个步骤来查找1,000,000条记录中的唯一值(如果内存服务)如果您正在使用索引。无论您使用的是复合索引还是独立索引,都是如此 - 但仅适用于第一个字段(在您的示例中为“种类”,尽管我认为您需要Family,Species和Common Name)。

现在,假设第一个字段值有100,000个匹配记录。如果您只有单个索引,那么这些记录中的任何查找都将需要100,000步:第一个索引检索的每个记录一个。这是因为不会使用第二个索引(在大多数数据库中 - 这有点简化)并且必须使用强力匹配。

如果您有复合索引,那么您的搜索速度会快得多,因为您的第二个字段搜索将在第一组值中包含索引。在这种情况下,您需要不超过17个步骤才能在第1场的100,000场比赛中获得第2场的第一个匹配值(记录基数2为100,000)。

所以:使用3个嵌套字段上的复合索引从1,000,000条记录的数据库中查找唯一记录所需的步骤,其中第一个检索100,000,第二个检索10,000 = 20 + 17 + 14 = 51步。

在相同条件下需要的步骤,只有独立指数= 20 + 100,000 + 10,000 = 110,020步。

差异很大,嗯?

现在,不要疯狂地将复合索引放在各处。首先,它们在插入和更新方面很昂贵。其次,如果您真正搜索嵌套数据,它们只会受到影响(换另一个例子,我在为给定日期范围内的客户端提取数据时使用它们)。此外,如果您使用相对较小的数据集,它们是不值得的。

最后,检查数据库文档。数据库在最近部署索引的能力方面变得非常复杂,上面描述的数据库101场景可能不适用于某些人(虽然我总是发展,好像它确实如此,我知道我得到了什么)。

答案 1 :(得分:10)

这两种方法不同。第一个在三个属性上创建一个索引,第二个创建三个单属性索引。存储要求会有所不同,虽然没有分配,但不可能说哪个会更大。

当您需要访问A,A + B和A + B + C的值时,索引三列[A,B,C]的效果很好。如果您的查询(或查找条件或其他内容)未引用A,则不会有任何好处。

当A,B和C分别编制索引时,一些DBMS查询优化器会考虑组合两个或多个索引(取决于优化程序的效率估计),以便为单个多列索引提供类似的结果。

假设您有一些电子商务系统。您想通过purchase_date,customer_id和有时两者查询订单。我首先创建两个索引:每个属性一个。

另一方面,如果您始终指定purchase_date customer_id,那么两列上的单个索引可能效率最高。订单很重要:如果您还想查询客户所有日期的订单,请将customer_id作为索引中的第一列。

答案 2 :(得分:1)

From the docs:

  

在多个上创建索引时   列,第一列用作   索引的名称。例如,何时   您在两列上指定索引   [:first,:last],DBMS创建一个   两列的索引以及一个   第一列的索引:第一列。   仅使用第一个名称   索引是有道理的,因为你会   永远不必创建一个单一的索引   用这个名字。

在创建复合索引时使用第一种方法,在单个属性上创建索引时使用第二种方法。

有一些好点here on when to use compound indexes,但要点是在多个属性上使用where时它们很好。请注意,它们应与其他索引一起使用(始终索引您的foriegn键) - 而不是替代。