Как уменьшить размер таблицы SQL Server, которая выросла после изменения типа данных - PullRequest
20 голосов
/ 30 апреля 2009

У меня есть таблица на SQL Server 2005 размером около 4 ГБ.

(около 17 миллионов записей)

Я изменил одно из полей с типа данных char(30) на char(60) (всего есть 25 полей, большинство из которых char(10), поэтому объем пространства символов составляет около 300)

Это привело к удвоению таблицы (более 9 ГБ)

Затем я изменил char(60) на varchar(60) и затем запустил функцию, чтобы вырезать лишние пробелы из данных (чтобы уменьшить среднюю длину данных в поле примерно до 15)

Это не уменьшило размер таблицы. Сжатие базы данных также не помогло.

Если не считать фактического воссоздания структуры таблицы и копирования данных (это 17 миллионов записей!), Есть ли менее радикальный способ снова уменьшить размер?

Ответы [ 5 ]

25 голосов
/ 30 апреля 2009

Вы не очищали и не сжимали никакие данные, даже с «сокращенной базой данных».

DBCC CLEANTABLE

Возвращает пространство из удаленных столбцов переменной длины в таблицах или индексированных представлениях.

Тем не менее, простая перестройка индекса при наличии кластерного индекса также должна это сделать

ALTER INDEX ALL ON dbo.Mytable REBUILD

Рабочий пример от Тони Роджерсона

17 голосов
/ 30 апреля 2009

Ну, ясно, что ты не получишь обратно места! : -)

Когда вы изменили свои текстовые поля на CHAR (60), они все заполняются до отказа пробелами. Так что ВСЕ ваши поля теперь имеют длину 60 символов.

Изменение этого значения обратно на VARCHAR (60) не поможет - поля все еще имеют длину 60 символов ....

Что вам действительно нужно сделать, так это запустить функцию TRIM для всех ваших полей, чтобы уменьшить их обратно до сокращенной длины, а затем выполнить сжатие базы данных.

После того, как вы это сделаете, вам нужно перестроить ваш кластерный индекс, чтобы освободить часть этого потраченного впустую пространства. Кластерный индекс действительно там, где живут ваши данные - вы можете перестроить его так:

ALTER INDEX IndexName ON YourTable REBUILD 

По умолчанию вашим первичным ключом является кластерный индекс (если не указано иное).

Марк

2 голосов
/ 30 апреля 2009

Я знаю, что я не отвечаю на ваш вопрос, как вы спрашиваете, но рассматривали ли вы возможность архивирования некоторых данных в таблицу истории и работы с меньшим количеством строк?

В большинстве случаев на первый взгляд может показаться, что вам нужны все эти данные постоянно, но когда вы на самом деле сидите и изучаете их, бывают случаи, когда это не так. Или, по крайней мере, я сталкивался с такой ситуацией раньше.

0 голосов
/ 30 апреля 2009

В качестве альтернативы, вы можете выполнить полную перестройку таблицы, чтобы убедиться, что нигде не осталось лишних данных:

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

Конечно, с идентификацией, индексами и т. Д. Все усложняется ...

0 голосов
/ 30 апреля 2009

У меня была похожая проблема здесь SQL Server, преобразование NTEXT в NVARCHAR (MAX) , что было связано с изменением ntext на nvarchar (max).

Я должен был сделать UPDATE MyTable SET MyValue = MyValue, чтобы заставить его правильно все изменить.

Это очевидно занимает довольно много времени с большим количеством записей. Было несколько предложений, как лучше это сделать. На первом ключе был временный флаг, обозначенный, если это было сделано, или нет, а затем обновлялось несколько тысяч за раз в цикле, пока все не было сделано. Это означало, что у меня был «некоторый» контроль над тем, сколько он делал.

С другой стороны, если вы действительно хотите максимально сократить базу данных, это может помочь, если вы превратите модель восстановления в простую, сократите журналы транзакций, реорганизуете все данные на страницах, а затем установите их вернуться к полной модели восстановления. Однако будьте осторожны, сокращение баз данных, как правило, нежелательно, и если вы уменьшаете модель восстановления действующей базы данных, вы просите что-то не так.

...