Звільнення невикористаного простору таблиці SQL Server


11

У мене є таблиця в SQL Server 2012 Express з великою кількістю невикористаного простору.

Мені потрібно звільнити місце в базі даних.

| ІМ’Я | РАДИ | ЗАБЕЗПЕЧЕНО | ДАНІ | INDEX_SIZE | Невикористаний |
| ------------- | -------- | -------------- | ----------- --- | ------------ | -------------- |
| MyTableName | 158890 | 8928296 Кб | 5760944 Кб | 2248 Кб | 3165104 Кб |

Як змусити SQL звільнити 3165104KB?

Я вже пробував:

Alter table MyTableName Rebuild
DBCC CLEANTABLE (MyDbName,"MyTableName ", 0)
ALTER INDEX ALL ON MyTableName REORGANIZE ; 
ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF) 

Ось таблиця:

CREATE TABLE [dbo].[MyTableName](
    [ImageID] [int] IDENTITY(1,1) NOT NULL,
    [DateScan] [datetime] NULL,
    [ScanImage] [image] NULL,
 CONSTRAINT [PK_Image] PRIMARY KEY CLUSTERED 
(
    [ImageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

Єдине, що ми зробили, це замінювати ScanImageв кожному рядку набагато менші зображення (саме стільки невикористаного простору там).

Відповіді:


10

Єдине, що ми зробили, це заміняти ScanImageв кожному рядку набагато менші зображення (це стільки невикористаного місця)

З деяких експериментів найбільш ефективним для простору методом було б скинути одиницю розподілу та переселити її (якщо у вас є вікно технічного обслуговування для цього).

Приклад коду, який досяг найкращого простору для мене зі структурою таблиці у питанні:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET XACT_ABORT ON;

BEGIN TRAN

SELECT [ImageID],
       [ScanImage]
INTO   #Temp
FROM   [dbo].[MyTableName]

ALTER TABLE [dbo].[MyTableName]
  DROP COLUMN [ScanImage]

/*Allocation unit not removed until after this*/
ALTER INDEX PK_Image ON MyTableName REBUILD

ALTER TABLE [dbo].[MyTableName]
  ADD [ScanImage] IMAGE NULL

UPDATE [dbo].[MyTableName]
SET    [ScanImage] = T.[ScanImage]
FROM   [dbo].[MyTableName] M
       JOIN #Temp T
         ON M.ImageID = T.[ImageID]

DROP TABLE #Temp

COMMIT 

Все відбувається в угоді, тому, якщо машина вийде з ладу, вона буде відкочена назад. Можливо, можливо, це стосується помилок або хоча б SET XACT_ABORT ON. Я використовував SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;для запобігання того, щоб будь-які паралельні модифікації відбувалися під час копіювання або після її втрати.

Кількість зарезервованих сторінок LOB після зменшення розміру imageв усіх рядках було наступним:

+ ------------------------------------------------- - + --------------------- + ------------------------- +
| Подія | lob_used_page_count | lob_reserved_page_count |
+ ------------------------------------------------- - + --------------------- + ------------------------- +
| Вкладено 10 000 рядків із 100 000 байтовими даними у кожному | 135005 | 135017 |
| Оновлено всі рядки до 10 000 байт даних зображення | 31251 | 135012 |
| Реорганізувати | 23687 | 25629 |
| Видалення та повторне додавання даних зображення | 13485 | 13489 |
+ ------------------------------------------------- - + --------------------- + ------------------------- +

1
Або якщо таблиця велика, тоді BCP виводить дані, а потім BULK INSERT знову в - під час вікна технічного обслуговування.
Кін Шах

6

Спробуйте

ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF)

Це відтворює кластерний індекс, тому для завершення операції вам знадобиться додаткове місце у вашій базі даних. Якщо у вас немає додаткового місця, оскільки ваш диск заповнений, ви, можливо, можете додати новий файл даних до бази даних (на іншому диску) і перемістити таблицю до нього.

Можливо також, що кластерний індекс визначається за допомогою FILLFACTOR менше 100%. Якщо встановити коефіцієнт заповнення, наприклад, 66%, залишиться 1/3 кожної сторінки даних порожнім для подальшого використання. Якщо це проблема, ви можете змінити коефіцієнт заповнення, використовуючиALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF, FILLFACTOR=100)

Якщо ви нещодавно скинули з таблиці поле змінної довжини, ви також можете спробувати DBCC CLEANTABLE( Databasename, "MyTableName")

Книги в Інтернеті (BOL) мають чудову статтю про відновлення індексів на веб-сторінці http://technet.microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx


2

Переконайтесь, що режим відновлення БД є SIMPLE.

змінити стовпчик як VARBINARY(MAX).

Потім спробуйте скопіювати дані в абсолютно нову таблицю.

Перевірте новий розмір таблиці за допомогою sp_spaceused "tablename". Якщо вас влаштовує невикористаний простір таблиці, перевірте невикористаний простір бази даних за допомогою тієї самої команди, не вказуючи ім’я таблиці. Цей простір все ще знаходиться у файлах бази даних і не випускається в ОС.

Ви можете кинути оригінальну таблицю та перейменувати нову таблицю, або зробити те ж саме знову, і використовувати оригінальне ім’я таблиці, якщо ви не довіряєте операції з перейменуванням, (я не вірю повністю).

Якщо це працює, то останній крок простий: ви знаєте, як зменшити файли та звільнити невикористаний простір.

Якщо є якісь закордонні ключі, запишіть їхні визначення, опустіть їх, виконайте завдання, про які я згадував вище, і відтворіть потім зовнішні ключі. Звичайно, це займе час, і цю операцію потрібно робити в неробочий час. Це все завдання можна виконати за допомогою сценарію, а також дозволити йому працювати протягом ночі.


1

Я просто створив би нову базу даних і скопіював у неї дані. Ви повинні мати можливість використовувати майстра імпорту / експорту. (Очевидно, резервна копія та відновлення утримають проблему.) Перевірте результати імпорту даних. Якщо все виглядає добре, перейменуйте оригінальну базу даних, а потім перейменуйте нову базу даних на ім'я, яке ви хочете використовувати. (Я завжди трохи зачекаю, перш ніж скинути оригінал, лише щоб двічі перевірити онлайн.)

Для того, що це варто, ми також відмовилися від блоків даних, якщо вони не надто великі, наступними кроками. (Однак, оскільки ви використовуєте SQL Server Express, можливо, вам не вистачить місця для того, щоб спробувати це.)

  1. Додайте новий файл до групи файлів.
  2. Біжи DBCC SHRINKFILE(file, EMPTYFILE). Оскільки ви скорочуєте MDF, він з часом вийде з ладу, оскільки метадані системи неможливо перемістити. Однак порожні виділення блобу не переміщені.
  3. Біжи DBCC SHRINKFILE(newfile,EMPTYFILE). Це перемістить дані назад за вирахуванням зайвого простору.
  4. Видаліть новий файл (тепер порожній) з групи файлів.

Це виключає набряк кишки. Слід зазначити, що ми використовували цю методику насамперед для створення переважно порожньої бази даних для тестування скриптів оновлення.


-1

Реорганізуйте кластерний індекс - той, що має дані у вузлах, так що .... він, швидше за все, фрагментований.


Я спробував запустити: ALTER INDEX ALL ON [MyTableName] REORGANIZE;
DermFrench

3
Перебудовуйте її;) Не реорганізуйте.
TomTom
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.