Утверждение места на диске после удаления поля таблицы

16

Я использую sql 2008 r2, и БД работала хорошо и быстро в течение последних 3 лет, пока 3 месяца назад мы не добавили поле ntext в очень активную и использованную таблицу. Теперь мы начинаем выходить из серверного пространства из-за огромного расширяющегося размера этой таблицы.

Я читал, что сжимаясь, мы не хотим терять индексацию БД, потому что она работала быстро в течение многих лет, и мы не хотим, чтобы фрагментация продолжалась.

Мы решили удалить это поле и все его значения: есть ли способ удалить поле ntext и все его значения и освободить пространство без удаления индексации, без сжатия, без потери производительности дБ?

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

введите описание изображения здесь

user1021182
источник

Ответы:

12

Мы решили удалить это поле и все его значения: есть ли способ удалить поле ntext и все его значения и освободить пространство без удаления индексации, без сжатия, без потери производительности дБ?

Я бы порекомендовал использовать (от BOL:)

DBCC CLEANTABLE
(
    { database_name | database_id | 0 }
    , { table_name | table_id | view_name | view_id }
    [ , batch_size ]
)
[ WITH NO_INFOMSGS ]

DBCC CLEANTABLE освобождает пространство после удаления столбца переменной длины. Столбец переменной длины может иметь один из следующих типов данных: varchar, nvarchar, varchar (max), nvarchar (max), varbinary, varbinary (max), текст, ntext, image, sql_variant и xml. Команда не освобождает пространство после удаления столбца фиксированной длины.

!! ВНИМАНИЕ !! ( используйте аккуратный размер пакета - желательно использовать этот параметр, если ваша таблица массивна) :

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

Эта операция полностью зарегистрирована.

Простое повторение докажет, что DBCC CLEANTABLEэто лучше, чем SHRINKING (и не беспокойтесь о фрагментации :-)

-- clean up
drop table dbo.Test

-- create test table with ntext column that we will drop later
create table dbo.Test (
    col1 int
    ,col2 char(25)
    ,col3 ntext
    );

-- insert  1000 rows of test data
declare @cnt int;

set @cnt = 0;

while @cnt < 1000
begin
    select @cnt = @cnt + 1;

    insert dbo.Test (
        col1
        ,col2
        ,col3
        )
    values (
        @cnt
        ,'This is a test row # ' + CAST(@cnt as varchar(10)) + 'A'
        ,REPLICATE('KIN', ROUND(RAND() * @cnt, 0))
        );
end

введите описание изображения здесь

введите описание изображения здесь

--drop the ntext column
ALTER TABLE dbo.Test DROP COLUMN col3 ;

введите описание изображения здесь

введите описание изображения здесь

--reclaim the space from the table
-- Note that my table is only having 1000 records, so I have not used a batch size
-- YMMV .. so find a maintenance window and you an appropriate batch size 
-- TEST TEST and TEST before implementing in PROD.. so you know the outcome !!
DBCC CLEANTABLE('tempdb', 'dbo.Test') ;

введите описание изображения здесь

введите описание изображения здесь

Кин Шах
источник
После того, как вы выполнили команду DBCC CLEANTABLE, вам нужно REBUILD ваш кластеризованный индекс в случае, если у таблицы есть такой, чтобы вернуть пространство. ALTER INDEX IndexName ON YourTable REBUILD;
г-н ТА
6

По большей части я ссылаюсь на серию блогов Пола Рэндалла « Внутри движка хранения »

Единственный способ вернуть неиспользуемое пространство из файлов базы данных в SQLServer - это использовать команду DBCC SHRINK, которая перераспределяет данные на страницах файлов базы данных, освобождая их, и после удаления их из карты Global Allcation удаляет их из файла базы данных. Эта операция медленная, создает фрагментацию в базе данных и еще медленнее при работе со страницами больших объектов, поскольку они хранятся в виде связанных списков в файлах базы данных.

Поскольку вы отбрасываете столбец NTEXT, вам придется подождать, пока процесс очистки призрака удалит данные, прежде чем сжиматься.

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

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

Spörri
источник
Будет ли процесс очистки призраков уменьшать пространство, или же потребуется сокращение?
user1021182
вам всегда придется сокращаться, процесс очистки только очищает выделенные страницы, но не удаляет их из файлов базы данных
Spörri
1
@ Spörri Since you are dropping the NTEXT column you will have to wait for the ghost cleanup process to drop the data before shrinking.Пожалуйста, посмотрите мой ответ . Вы можете использовать, DBCC CLEANTABLEчтобы освободить место.
Кин Шах
4

Вы хотите сжать файлы базы данных, потому что вам нужно это пространство для других баз данных / файлов, не относящихся к БД, или из-за проблем с этой базой данных, на которой заканчивается свободное место?

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

Кеннет Фишер
источник
у нас осталось всего 10 ГБ на диске, и через несколько дней он закончится. мы удалили все, что могли удалить с сервера, использовали очистку и остановили обновления Windows, удалили их все и очистили winsxs, теперь мы должны уменьшить размер файла db
user1021182
Опять же, помните, что после удаления дополнительного столбца рост вашей БД на некоторое время прекратится, пока вы будете заполнять новое свободное место. Если после этого момента ваша БД продолжает расти, то вам абсолютно необходимо дополнительное дисковое пространство для вашей базы данных. Возможно, добавьте новый диск на ваш сервер.
Кеннет Фишер
0

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

ardochhigh
источник
в этом случае все индексы также должны быть подготовлены
user1021182
да, любые индексы, влияющие на таблицу, нужно будет также удалить и воссоздать .... также относится к другим объектам, ссылающимся на таблицу, например: триггеры
ardochhigh