sql-server - 修改大型数据库的策略
问题描述
我正在为即将到来的重大变化测试不同的策略。问题是每个实验都会在 Azure 中产生一些成本。数据量很大,而且在我认识这家公司之前,由于多年的修复和交易,可能会有一些不一致的地方。
我需要更改具有数百万条记录和数十个索引的表中的列。这将有很大的停机时间。
ALTER TABLE X ALTER COLUMN A1 decimal(15, 4) --原始列是int
最初的想法之一(现在我知道这是不可能的)是拥有一个辅助副本,在那里进行更改,并且当更改完成时,将主副本与辅助副本交换......零或几乎零停机时间。我指的是“实时”的冗余副本,而不仅仅是“副本”
编辑:提出新想法:
- 一个答案中提到的变化:创建一个表副本(不是整个数据库,只是表),应用 INSERT INTO... SELECT 并在过程结束时交换表。或者... 尽早进行交换,以最大限度地减少在添加源中的所有记录期间延迟的停机时间
我已经尝试过了,但需要 AGES 才能完成。此外,一些 null 和 FK 违规会在处理几个小时后导致进程失败。“恢复”可能是一个选项,但它会使每次执行的过程变慢。没有某种“简历”,每次失败都得从头开始重复
一个可接受的改进可能是忽略错误(当然是创建日志)并在迁移后应用修复。但是 afaik,AzureSql(也不是 SqlServer)不提供“忽略”选项
- 将所有索引、约束和依赖项删除到需要修改的列,修改列并再次应用所有索引、约束和依赖项。
也试过这个。一些索引需要 AGES 才能完成。但目前看来是最好的选择。在数据类型更改之前应用 ROW COMPRESSION 可能会产生变化,但我认为它不会改善实际情况:索引重新创建
- 使用目标数据类型创建一个新列,从源列复制数据,删除旧列并重命名新列。此策略还需要删除和重新生成索引,因此它不会提供关于#2 的大量收益(如果有的话)。
有朋友想到了一个变种,就是在线复制列拷贝所需的索引。同时,将源列上的所有更改触发到列副本。
对于任何提到的策略,可以通过增加处理能力来获得一些收益。但是,无论如何,我们考虑使用任何方法来增加功率,因此这对于所有解决方案都是常见的
解决方案
当您需要将 A LOT 的行更新为一次性事件时,使用以下迁移技术可能更有效:
- 创建一个新的目标表
- 使用INSERT INTO SELECT用正确/更新的值填充新表
- 重命名 旧表和新表
- 为新表创建索引
推荐阅读
- python - 奇怪的模运算符 (%) 结果
- c# - 无法将名称中包含“[”的文件上传到 IBM Cloud Object Storage
- java - Spring Boot Jackson Databind - 配置继承
- python - += 更新 pandas datadame 中的行
- android - Google Play 突然反对我的应用签名无效
- python - 我无法让我的烧瓶用户注册码工作,我做错了什么?
- android - Xamarin,列表视图更新
- javascript - 从客户端传递引用并获取 node.js 中的 headers.referer
- sql - 使用组合框和 SQL 在 Access 中无效使用属性
- java - clientkeystore 访问被拒绝