【问题标题】:When to add what indexes in a table in Rails何时在 Rails 中的表中添加哪些索引
【发布时间】:2011-04-09 04:49:49
【问题描述】:

我有一个关于 Rails 数据库的问题。

  • 我应该将“index”添加到“xxx_id”等所有外键吗?
  • 我应该在自动创建的“id”列中添加“index”吗?
  • 我应该将“index(unique)”添加到自动创建的“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 添加“唯一索引”,对吗?

【问题讨论】:

    标签: mysql ruby-on-rails activerecord


    【解决方案1】:

    我应该将“index”添加到像“xxx_id”这样的所有外键吗?

    这样会更好,因为它加速了在此列中排序的搜索。外键搜索量很大。

    从第 5 版开始,索引将自动创建,更多信息请参阅here

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

    不,这已经由 rails 完成了

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

    不,同上

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

    那么索引就是两列的组合索引。这没有任何意义,除非您想要一个 category_id AND 一个 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

    【讨论】:

    • 很好的答案。附加问题。我应该为 xxx_id 添加“唯一索引”,对吧?
    • 问题,如果该字段很少被显式搜索,您会索引外键吗?
    • @Cyle 我不能肯定地回答这个问题,这取决于您的机器、数据库的大小以及查询的性质。如果查询来自网络,我可能会说是,因为获得快速响应总是更好,如果它用于后台作业并且您需要节省磁盘空间,则不需要设置它,但如果磁盘空间无论如何我都不会添加索引。
    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

    • 我很好奇如果你总是想为每个外键使用索引,为什么 Rails 不暗示索引。是否存在不对其进行索引的情况?
    • @trip 对于简单的情况,将index: true 添加到列定义中非常容易,但有时您可能希望对其进行更多控制。默认情况下在外键上设置索引并不是一个糟糕的默认设置,但它可能会让人们大吃一惊。
    【解决方案3】:
    • 始终索引外键
    • 始终为您排序的列编制索引
    • 所有唯一字段(以确保数据库级别的唯一性。迁移示例: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?,以及上面的答案。

    【讨论】:

      猜你喜欢
      • 2016-03-02
      • 2010-09-23
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      • 1970-01-01
      相关资源
      最近更新 更多