【问题标题】:Rails: Adding an index after adding columnRails:添加列后添加索引
【发布时间】:2013-03-30 16:35:28
【问题描述】:

假设我在 Rails 应用程序中创建了一个表 table。一段时间后,我添加了一个正在运行的列:

rails generate migration AddUser_idColumnToTable user_id:string. 

然后我意识到我需要添加user_id 作为索引。我知道add_index 方法,但是应该在哪里调用这个方法呢?我是否应该运行迁移(如果是,是哪个?),然后手动添加此方法?

【问题讨论】:

    标签: ruby-on-rails indexing migration


    【解决方案1】:

    你可以运行另一个迁移,只是为了索引:

    class AddIndexToTable < ActiveRecord::Migration
      def change
        add_index :table, :user_id
      end
    end
    

    【讨论】:

    • 所以我只是在控制台中运行:rails generate migration AddIndexToTable ?
    • 是的,您可以这样做,但您必须在之后编辑该迁移以反映上述代码。
    • :table 应该是复数吗?
    • @tomb 我使用了原始问题中的示例。 :table 是实际的表名,因此对于 users 表,您可以将 :users 替换为 :table
    【解决方案2】:

    如果您需要创建user_id,那么可以合理地假设您正在引用用户表。在这种情况下,迁移应为:

    rails generate migration AddUserRefToProducts user:references
    

    此命令将生成以下迁移:

    class AddUserRefToProducts < ActiveRecord::Migration
      def change
        add_reference :user, :product, index: true
      end
    end
    

    运行rake db:migrate 后,user_id 列和索引都将添加到products 表中。

    如果您只需要向现有列添加索引,例如nameuser 表,以下技术可能会有所帮助:

    rails generate migration AddIndexToUsers name:string:index 将生成以下迁移:

    class AddIndexToUsers < ActiveRecord::Migration
      def change
        add_column :users, :name, :string
        add_index :users, :name
      end
    end
    

    删除add_column 行并运行迁移。

    在所描述的情况下,您可以发出rails generate migration AddIndexIdToTable index_id:integer:index 命令,然后从生成的迁移中删除add_column 行。但我宁愿建议撤消初始迁移并添加参考:

    rails generate migration RemoveUserIdFromProducts user_id:integer
    rails generate migration AddUserRefToProducts user:references
    

    【讨论】:

    • 感谢 Vadym 提供完整的答案。最后一个问题:您为什么建议撤消初始迁移?以后添加索引是否有任何性能问题?
    • 致@fwuensche:以后添加索引不会造成性能损失。但是,域逻辑将不太清楚。例如。如果您稍后决定打破/抽象/等关联,您需要处理两个单独的迁移,这实际上应该是一个......
    • 警告:请注意 index: true 仅适用于 create_table 迁移。迁移将运行,但不会创建索引。见makandracards.com/makandra/…
    • 如果在 user_id 列已经投入生产之后发生“然后我意识到我需要添加 user_id 作为索引”,那么删除它会删除真实数据,所以这是个坏主意。如果它仍在开发中,为什么不直接还原然后编辑原始迁移?或者,如果您觉得需要保留原始迁移代码不变,您可以添加 cmets 提及两个迁移之间的关系。
    【解决方案3】:

    在创建列后添加生成的迁移如下(示例)

    add_index :photographers, :email, :unique => true
    

    【讨论】:

    • 你的意思是这样的:def self.up add_column ... end add_index ... ?
    【解决方案4】:

    参考资料可致电

    rails generate migration AddUserIdColumnToTable user:references
    

    如果将来您需要添加一个通用索引,您可以启动它

    rails g migration AddOrdinationNumberToTable ordination_number:integer:index
    

    生成代码:

    class AddOrdinationNumberToTable < ActiveRecord::Migration
      def change
       add_column :tables, :ordination_number, :integer
       add_index :tables, :ordination_number, unique: true
      end
    end
    

    【讨论】:

      【解决方案5】:

      你可以使用这个,只要认为 Job 是你要添加索引的模型的名称 cader_id

      class AddCaderIdToJob < ActiveRecord::Migration[5.2]
        def change
          change_table :jobs do |t|
            t.integer :cader_id
            t.index :cader_id
          end
        end
      end
      

      【讨论】:

        【解决方案6】:

        对于那些使用 postgresql db 并面临错误的人

        StandardError: An error has occurred, this and all later migrations canceled:
        
        === Dangerous operation detected #strong_migrations ===
        
        Adding an index non-concurrently blocks writes
        

        请参考this article

        示例:

        class AddAncestryToWasteCodes < ActiveRecord::Migration[6.0]
          disable_ddl_transaction!
        
          def change
            add_column :waste_codes, :ancestry, :string
            add_index :waste_codes, :ancestry, algorithm: :concurrently
          end
        end
        

        【讨论】:

          猜你喜欢
          • 2016-03-02
          • 2011-04-09
          • 2011-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          • 2020-05-28
          相关资源
          最近更新 更多