2010-09-07 61 views
114

我有一个关于Rails数据库的问题。什么时候添加Rails中的表中的索引

  • 我是否应该将“索引”添加到所有外键,如“xxx_id”?
  • 我应该将“索引”添加到自动创建的“id”列吗?
  • 我应该在自动创建的“id”列中添加“索引(唯一)”吗?

  • 如果我一次(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吧?

回答

157

我应该在“xxx_id”这样的所有外键上添加“index”吗?

这样会更好,因为它加速了本专栏排序的搜索。而外键是搜索了很多东西。

我应该将“索引”添加到自动创建的“id”列吗?

不,这已经被轨道

做我应该加上“指数(唯一)”,以自动创建的“ID”列?

没有,同上

如果我一次添加索引的两个外键(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的伟大answer

+3

很好的回答。附加问题。我应该为xxx_id添加“唯一索引”,对吗? – 2010-09-08 01:17:52

+0

不,请参阅我的更新回答 – jigfox 2010-09-08 07:04:07

+0

问题,如果该字段很少显式搜索,您会索引外键吗? – Noz 2013-02-06 19:12:49

98

索引可能是一个棘手的,微妙的事情,但有一些通用的规则可以决定哪些使用更容易。

首先要记住的是索引可以以多种方式工作。 A,B,C上的索引也适用于A,B和简单的A,因此如果您正确命令它们,您可以将索引设计得更加通用。电话簿以姓氏,名字索引,因此您可以通过姓氏或姓氏和名字的组合轻松查找人员。然而,你不能直接用他们的名字来查看它们。你需要一个单独的索引。电话号码也是一样,你也必须索引。

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

  • 如果你有一个belongs_to - has_many关系配对,你必须使用的外键的索引。
  • 如果您订购了您的记录,并且有大量这些记录将进行分页,那么您应该将该订单列添加到索引的末尾。
  • 如果你有has_many :through关系,你的连接表应该对参与合并为一个复合键两个属性的唯一索引。
  • 如果你取一个记录直接使用一个唯一的标识符,如用户名或电子邮件,这应该是一个唯一索引。
  • 如果取套的使用范围从has_many关系记录,确保有包含has_many外键的顺序范围列的索引。

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

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

+0

我很好奇,为什么Rails不暗示索引,如果你总是想要为每个外键使用它们。是否有这样的情况,索引它不是一个好主意? – Trip 2014-10-23 18:30:02

+1

@trip在简单情况下为列定义添加'index:true'非常容易,但有时您可能需要对其进行更多的控制。默认情况下在外键上有索引并不是一个可怕的默认设置,但它可能让人惊讶。 – tadman 2014-10-23 18:52:09

7
  • 始终指标外键
  • 始终索引列你会
  • 订单的所有独特的字段(以确保唯一性在数据库级别实例迁移:add_index :users, :email, unique: true
  • 如果您订购的两件事情,或由两件事情进行搜索,例如: 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-indexesrails - created_at when user for ordering, Should you add an Index to the table?,以上问题的答案。

相关问题