何时在Rails的表中添加什么索引


131

我对Rails数据库有疑问。

  • 我应该在所有外键(例如“ xxx_id”)上添加“ index”吗?
  • 我应该在自动创建的“ id”列中添加“ index”吗?
  • 我应该在自动创建的“ id”列中添加“ index(unique)”吗?

  • 如果我一次将索引添加到两个外键(add_index (:users, [:category, :state_id]),会发生什么呢?与为每个键添加索引有何不同?

    class CreateUsers < ActiveRecord::Migration
      def self.up
        create_table :users do |t|
          t.string :name
          t.integer :category_id 
          t.integer :state_id
          t.string :email
          t.boolean :activated
          t.timestamps
        end
      # Do I need this? Is it meaningless to add the index to the primary key?
      # If so, do I need :unique => true ?
      add_index :users, :id 
      # I don't think I need ":unique => true here", right?
      add_index :users, :category_id # Should I need this?
      add_index :users, :state_id # Should I need this?
      # Are the above the same as the following?
      add_index (:users, [:category, :state_id])
      end
    end

到目前为止,很好的答案。附加问题。

  • 我应该为xxx_id添加“唯一索引”,对吧?

Answers:


175

我应该在所有外键(例如“ xxx_id”)上添加“ index”吗?

这样做会更好,因为它可以加速此列中的排序搜索。而且外键搜索很多。

从rails的第5版开始,索引将自动创建,有关更多信息,请参见此处

我应该在自动创建的“ id”列中添加“ index”吗?

不,这已经通过铁路完成

我应该在自动创建的“ id”列中添加“ index(unique)”吗?

不,和上面一样

如果我一次将索引添加到两个外键(add_index (:users, [:category_id, :state_id]),会发生什么呢?与为每个键添加索引有何不同?

然后,索引是两列的组合索引。这并没有任何意义,除非你想为一个所有条目category_id 一个state_id(应该category_id不是category在同一时间)。

这样的索引可以加快以下请求的速度:

# rails 2
User.find(:all, :conditions => { :state_id => some_id, :category_id => some_other_id })

# rails 3
User.where(:state_id => some_id, :category_id => some_other_id)

哪里

add_index :users, :category_id
add_index :users, :state_id

将加快这些请求:

# rails 2+3
User.find_by_category_id(some_id)
User.find_by_state_id(some_other_id)

# or
# rails 2
User.find(:all, :conditions => {:category_id => some_id})
User.find(:all, :conditions => {:state_id => some_other_id})

# rails 3
User.where(:category_id => some_id)
User.where(:state_id => some_other_id)

我应该为xxx_id添加“唯一索引”,对吧?

不,因为如果你这样做,只有一个用户可以在一个类别,但类别的意思是,你可以把更多的许多用户归为一类。在您的User模型中,您会有类似的内容belongs_to :category,在类别模型中,您会有类似的内容has_many :users。如果您有has_many关系,则该foreign_key字段不能唯一!

有关此的更多详细信息,您应该看一下tadman的一个很好的答案


3
好答案。附加问题。我应该为xxx_id添加“唯一索引”,对吧?
传统知识。

问题,如果很少显式搜索该字段,您会索引外键吗?
Noz

@Cyle我绝对不能回答这个问题,它取决于您的计算机,数据库的大小以及查询的性质。如果查询来自网络,我可能会说“是”,因为获得快速响应总是更好,如果是后台作业,并且您需要节省磁盘空间,则不需要设置它,但是如果磁盘空间无论如何,我都不会添加索引。
jigfox

111

索引可能是一件棘手的,微妙的事情,但是有一些适用的通用规则可以使确定使用哪种规则变得容易得多。

要记住的第一件事是索引可以以多种方式工作。A,B,C上的索引也适用于A,B以及仅适用于A的索引,因此,如果正确订购索引,则可以将其设计为用途更广泛的索引。电话簿在“姓氏,名字”上建立了索引,因此您可以轻松地通过他们的姓氏或姓氏和名字的组合来查找人们。但是,您不能直接通过其名字查找它们。您需要一个单独的索引。电话号码也是如此,您也必须为其编制索引。

考虑到这一点,有许多事情将决定如何创建索引:

  • 如果您具有belongs_to- has_many关系配对,则需要在所使用的外键上有一个索引。
  • 如果您对记录进行排序,并且其中有很多记录将被分页,则应将该订单列添加到索引的末尾。
  • 如果存在has_many :through关系,则联接表在联接所涉及的两个属性上都应具有唯一索引(作为复合键)。
  • 如果您使用唯一的标识符(例如用户名或电子邮件)直接获取记录,则该标识符应该是唯一的索引。
  • 如果您has_many使用范围从关系中获取记录集,请确保存在一个包含该has_many顺序的外键和范围列的索引。

索引的目的是消除在数据未正确索引时发生的可怕的“表扫描”或“文件排序”操作。

简而言之,请查看您的应用程序正在生成的查询,并确保以该顺序表示WHEREHAVING条件和ORDER BY子句中引用的列。


1
我很好奇为什么Rails并不隐含索引,如果您总是想对每个外键使用索引的话。是否存在索引不是一个好主意的情况?
2014年

1
@trip index: true对于简单的情况,很容易将其添加到列定义中,但是有时您可能希望对其进行更多控制。默认情况下,在外键上拥有索引并不是一个可怕的默认值,但是它可能会让人们感到意外。
塔德曼,2014年

13
  • 总是索引外键
  • 始终索引您要排序的列
  • 所有独特的字段(以确保唯一性在数据库级别实例迁移。add_index :users, :email, unique: true
  • 如果按2进行排序,或按2进行搜索,例如: order by [a, b]find where( a and b ),则需要一个双索引:

具体示例:

如果你有:

default_scope :order => 'photos.created_at DESC, photos.version DESC'

您应该添加:

add_index :photos, [:created_at, :version]

注意:索引会占用磁盘上的额外空间,并使创建和更新每个记录的速度变慢,因为它必须重建每个索引。

信用:

https://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes导轨- created_at当用户订购,你应该添加一个索引表?,以及以上答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.