当你需要改变Materialized View所使用的某个表的列的类型时,会发生什么情况。你是如何做到这一点的?假设你想把products.name从string 改为text ,你需要生成一个迁移。
rails g migration change_products_name
有以下内容。
class ChangeProductsName < ActiveRecord::Migration
def up
drop_view :expensive_products, materialized: true
change_column :products, :name, :text
create_view :expensive_products, materialized: true
# If we had more versions for this materialized we would use the latest
# generated instruction, something like:
#
# update_view :expensive_products, version: 2, revert_to_version: 1, materialized: true
add_index :expensive_products, :id, unique: true
end
def down
drop_view :expensive_products, materialized: true
change_column :products, :name, :string
create_view :expensive_products, materialized: true
# Similar to "#up" we would do the same:
#
# update_view :expensive_products, version: 2, revert_to_version: 1, materialized: true
add_index :expensive_products, :id, unique: true
end
end
从这个迁移的代码中可以看出,重要的是我们如何进行修改以更新表,然后,在这之后,我们创建或更新物化视图,取决于我们已经有多少个版本。
关于这一切的重要问题是。这是正确的方法吗?如果你没有真正的实时流量,或者你不介意在数据库进行修改的时候出现错误,这绝对是一个好方法。
当你的系统有大量的流量时,你需要小心并尊重你的客户,对我来说,处理这样的变化的最好方法是做以下事情。
- 创建一个单一的迁移,在表中添加一个具有你想使用的正确类型的新列。
- 创建一个dumpsterrake任务,将数据从旧列复制到新列。
- 更新你的视图,如果有的话,以使用这个新列。
- 创建一个新的物化视图,使用这个新列而不是其他列。
- 更新你的模型和self.table_name到这个新的物化视图。
- 进行发布
- 创建一个与上面类似的迁移,做一些你想要的改变。
- 再次,创建一个dumpsterrake任务,在这种情况下,将数据从新列复制到旧列。
- 再次,更新你的视图,如果有的话,以使用旧的列。
- 再次,更新你的模型以使用旧的self.table_name。
- 进行发布
我知道上面所有的步骤看起来都是多余的,但事实是,如果你想让你的系统保持100%的正常运行时间,错误和用户投诉的数量几乎为零,这基本上是唯一的办法了。