ani*_*ick 2 t-sql sql-server sql-server-2012
我有一个包含超过 1.5 亿条记录的表。目前的类型是:
id (Primary Key, Bigint)
idResult (Foreign key, Bigint null)
idItem (Foreign Key, Bigint null)
Number_1 (Bigint null)
Number_2 (Bigint null)
IsActive (Bigint null)
Run Code Online (Sandbox Code Playgroud)
Number_1 和 Number_2 永远不能大于 10。IsActive 显然是一个布尔值。并且这些列在代码库中的任何其他地方都不可以为空。我还想将外键字段更改为 int,但那又是另外一回事了。这张桌子是在我开始之前几年建造的,我们正在经历一些成长的痛苦。
我正在寻找转换这些列(以及其他表上的其他几个列,尽管这是主要的违规者)并回收该磁盘空间的最佳方法。我已经尝试了一个直接的Alter Table,但是,有点出乎意料,只是没有奏效。我不记得具体的错误,但我相信它与相关表格的大小有关。
现在我正在考虑手动删除并重新创建表,但我正在努力找出更好的方法来做到这一点,而不是使用 a Select TOP 10000 * FROM dbo.TABLENAME WHERE id > 0,并且简单地多次增加 where 子句。
我看过了Switch To,但这要求目标表的数据类型与源表匹配,这就是我要修复的问题!
有什么建议?我是不是看错了?
首先,谢谢你这样做。这是一场如此明显的胜利,以至于很多人都看不到它有多大价值,但这将是非常值得的:)。让世界变得更加理智。
关于IsActive成为布尔值。我的猜测是你正在考虑把它变成一个BIT领域。这可能是要走的路,但有时最好选择,TINYINT因为有可能将含义扩展到 2 个以上的状态。在这种情况下,它真的变得更多了StatusID。通常情况下,事情一开始就简单地为Active / Inactive,但后来可能是Deleted和/或其他。从大小的角度来看,TINYINT始终为 1 个字节。另一方面,最多 8 个字段BIT是 1 个字节。意思是,一个字段是 1 个字节,2 个字段也是一个字节,依此类推,最多 8 个BITBITBITBIT字段存储在单个字节中。那么,有没有节省空间选择BIT了TINYINT当表只有1BIT场。只是需要考虑的事情。
如您所见,对大表执行 ALTER TABLE 有点多。一种选择,虽然不是一个很好的选择,是添加一个NOT NULL字段 -- Number_1new-- 带有一个DEFAULT值(由于默认值,这将是即时的,至少从 SQL 2012 开始),它们都不会自然具有(例如 255),然后在循环中缓慢迁移值,如下所示:
UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;
Run Code Online (Sandbox Code Playgroud)
完成后,请执行以下操作:
sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';
Run Code Online (Sandbox Code Playgroud)
当然,最好将其包装在 TRANSACTION 中,并将其包装在 TRY / CATCH 中。当相关代码已经更新并且一切都已经测试并且数据看起来不错时,那么您可以删除该Number_1old列。
然而,我发现的最好方法是创建一个新表,慢慢地转换数据,然后同时交换表和代码。我在 SQL Server Central 上的一篇文章中详细介绍了这些步骤:在几秒钟内重构 1 亿行(或更多)表。SRSLY!(需要免费注册)。以防万一该文章出现问题,以下是基本步骤:
AFTER UPDATE, DELETE在 [table] 上添加触发器以保持更改同步(但无需担心新行)INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id].INTs的两个 FK 的 PK 引用),那么INT现在在此处创建这些字段,并且在将这些其他表迁移到具有之前不要添加 FK INT 字段作为它们的 PK。您不想为了对 FK 字段进行更改而再次重建此表。