如何减少因数据类型更改而增长的 SQL Server 表的大小

发布于 2024-07-17 15:07:20 字数 428 浏览 7 评论 0原文

我在 SQL Server 2005 上有一个大小约为 4GB 的表。

(大约 1700 万条记录)

我将其中一个字段从数据类型 char(30) 更改为 char(60) (总共 25 个字段,其中大部分是 char(10),因此字符空间量总计约为 300)

这导致表的大小加倍(超过 9GB),

然后我将 char(60) 更改为 < code>varchar(60) 然后运行一个函数从数据中删除多余的空格(以便将字段中数据的平均长度减少到大约 15)

这并没有减少表的大小。 缩小数据库也没有帮助。

除了实际重新创建表结构并复制数据(即 1700 万条记录!)之外,是否还有一种不太激烈的方法可以再次减小大小?

I have a table on SQL Server 2005 that was about 4gb in size.

(about 17 million records)

I changed one of the fields from datatype char(30) to char(60) (there are in total 25 fields most of which are char(10) so the amount of char space adds up to about 300)

This caused the table to double in size (over 9gb)

I then changed the char(60) to varchar(60) and then ran a function to cut extra whitespace out of the data (so as to reduce the average length of the data in the field to about 15)

This did not reduce the table size. Shrinking the database did not help either.

Short of actually recreating the table structure and copying the data over (that's 17 million records!) is there a less drastic way of getting the size back down again?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

番薯 2024-07-24 15:07:20

即使使用“收缩数据库”,您也没有清理或压缩任何数据。

DBCC CLEANTABLE

从表或索引视图中删除的可变长度列回收空间。

但是,简单的索引重建 如果有聚集索引也应该这样做

ALTER INDEX ALL ON dbo.Mytable REBUILD

已成功托尼·罗杰森的示例

You have not cleaned or compacted any data, even with a "shrink database".

DBCC CLEANTABLE

Reclaims space from dropped variable-length columns in tables or indexed views.

However, a simple index rebuild if there is a clustered index should also do it

ALTER INDEX ALL ON dbo.Mytable REBUILD

A worked example from Tony Rogerson

悍妇囚夫 2024-07-24 15:07:20

很明显你没有得到任何空间! :-)

当您将文本字段更改为 CHAR(60) 时,它们都被空格填满。 所以您的所有字段现在实际上都是 60 个字符长。

将其改回 VARCHAR(60) 不会有帮助 - 这些字段仍然是 60 个字符长......

您真正需要做的是对所有字段运行 TRIM 函数以将它们减少回修剪后的长度,并且然后进行数据库收缩。

完成此操作后,您需要重建聚集索引以回收一些浪费的空间。 聚集索引实际上是您的数据所在的位置 - 您可以像这样重建它:

ALTER INDEX IndexName ON YourTable REBUILD 

默认情况下,您的主键是聚集索引(除非您另外指定)。

马克

Well it's clear you're not getting any space back ! :-)

When you changed your text fields to CHAR(60), they are all filled up to capacity with spaces. So ALL your fields are now really 60 characters long.

Changing that back to VARCHAR(60) won't help - the fields are still all 60 chars long....

What you really need to do is run a TRIM function over all your fields to reduce them back to their trimmed length, and then do a database shrinking.

After you've done that, you need to REBUILD your clustered index in order to reclaim some of that wasted space. The clustered index is really where your data lives - you can rebuild it like this:

ALTER INDEX IndexName ON YourTable REBUILD 

By default, your primary key is your clustered index (unless you've specified otherwise).

Marc

谈场末日恋爱 2024-07-24 15:07:20

我知道我没有回答您所问的问题,但是您是否考虑过将一些数据存档到历史表中,并使用更少的行?

大多数时候,乍一看您可能会认为您一直需要所有这些数据,但当实际坐下来检查它时,在某些情况下事实并非如此。 或者至少我以前经历过这种情况。

I know I'm not answering your question as you are asking, but have you considered archiving some of the data to a history table, and work with fewer rows?

Most of the times you might think at first glance that you need all that data all the time but when actually sitting down and examining it, there are cases where that's not true. Or at least I've experienced that situation before.

瑕疵 2024-07-24 15:07:20

我在这里遇到了类似的问题 SQL Server,将 NTEXT 转换为 NVARCHAR(MAX)这与将 ntext 更改为 nvarchar(max) 有关。

我必须执行 UPDATE MyTable SET MyValue = MyValue 才能让它很好地调整所有内容的大小。

这显然需要相当长的时间和大量的记录。 关于如何更好地做到这一点,有很多建议。 他们的关键之一是一个临时标志,指示它是否已完成,然后循环一次更新几千个,直到全部完成。 这意味着我可以“部分”控制它的工作量。

另一方面,如果您确实想尽可能地缩小数据库,那么将恢复模式降低为简单、缩小事务日志、重新组织页面中的所有数据,然后将其设置回完整状态会有所帮助。恢复模型。 但要小心,收缩数据库通常是不可取的,如果你减少实时数据库的恢复模型,你就会导致出现问题。

I had a similar problem here SQL Server, Converting NTEXT to NVARCHAR(MAX) that was related to changing ntext to nvarchar(max).

I had to do an UPDATE MyTable SET MyValue = MyValue in order to get it to resize everything nicely.

This obviously takes quite a long time with a lot of records. There were a number of suggestions as how better to do it. They key one was a temporary flag indicated if it had been done or not and then updating a few thousand at a time in a loop until it was all done. This meant I had "some" control over how much it was doing.

On another note though, if you really want to shrink the database as much as possible, it can help if you turn the recovery model down to simple, shrink the transaction logs, reorganise all the data in the pages, then set it back to full recovery model. Be careful though, shrinking of databases is generally not advisable, and if you reduce the recovery model of a live database you are asking for something to go wrong.

请远离我 2024-07-24 15:07:20

或者,您可以进行完整的表重建,以确保任何地方都没有多余的数据:

CREATE TABLE tmp_table(<column definitions>);
GO
INSERT INTO tmp_table(<columns>) SELECT <columns> FROM <table>;
GO
DROP TABLE <table>;
GO
EXEC sp_rename N'tmp_table', N'<table>';
GO

当然,身份、索引等事情会变得更加复杂......

Alternatively, you could do a full table rebuild to ensure there's no extra data hanging around anywhere:

CREATE TABLE tmp_table(<column definitions>);
GO
INSERT INTO tmp_table(<columns>) SELECT <columns> FROM <table>;
GO
DROP TABLE <table>;
GO
EXEC sp_rename N'tmp_table', N'<table>';
GO

Of course, things get more complicated with identity, indexes, etc etc...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文