Как уменьшить размер таблицы SQL Server, который увеличился в результате изменения типа данных

StackOverflow https://stackoverflow.com/questions/807579

Вопрос

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

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

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

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

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

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

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

Это было полезно?

Решение

Ну, это же ясно, что ты не получишь обратно никакого пространства!:-)

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

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

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

После того, как вы это сделаете, вам нужно ПЕРЕСТРОИТЬ свой кластеризованный индекс, чтобы освободить часть этого потраченного впустую пространства.Кластеризованный индекс - это действительно то место, где хранятся ваши данные - вы можете перестроить его следующим образом:

ALTER INDEX IndexName ON YourTable REBUILD 

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

Марк

Другие советы

Вы не очищали и не уплотняли какие-либо данные, даже с помощью "сжатой базы данных".

DBCC ОЧИЩАЕМЫЙ

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

Однако, a простое перестроение индекса если существует кластеризованный индекс тоже следует это сделать

ALTER INDEX ALL ON dbo.Mytable REBUILD

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

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

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

У меня была похожая проблема здесь SQL Server, Преобразующий NTEXT в NVARCHAR (МАКСИМУМ) это было связано с изменением ntext на nvarchar (максимум).

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top