Membebaskan tabel SQL Server Space yang tidak digunakan

11

Saya punya tabel di SQL Server 2012 Express dengan banyak ruang yang tidak digunakan.

Saya perlu mengosongkan ruang dalam database.

| NAME | BARIS | DILINDUNGI | DATA | INDEX_SIZE | UNUSED |
| ------------- | -------- | -------------- | ----------- --- | ------------ | -------------- |
| MyTableName | 158890 | 8928296 KB | 5760944 KB | 2248 KB | 3165104 KB |

Bagaimana cara saya mendapatkan SQL untuk merilis 3165104KB?

Saya sudah mencoba:

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) 

Ini tabelnya:

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

Satu-satunya hal yang telah kami lakukan diganti ScanImagepada setiap baris dengan gambar yang jauh lebih kecil (ini adalah seberapa banyak ruang yang tidak digunakan di sana).

DermFrench
sumber

Jawaban:

10

Satu-satunya hal yang telah kami lakukan diganti ScanImagepada setiap baris dengan gambar yang jauh lebih kecil (ini adalah seberapa banyak ruang yang tidak digunakan di sana)

Dari melakukan beberapa eksperimen, metode yang paling efektif untuk ruang adalah dengan menjatuhkan unit alokasi dan mengisi kembali itu (jika Anda memiliki jendela pemeliharaan untuk melakukan hal ini).

Contoh kode yang mencapai pengurangan ruang terbaik bagi saya dengan struktur tabel dalam pertanyaan adalah:

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 

Semuanya dalam transaksi jadi jika mesin crash itu akan dibatalkan. Mungkin bisa dilakukan dengan beberapa penanganan kesalahan atau setidaknya SET XACT_ABORT ON. Saya digunakan SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;untuk mencegah modifikasi bersamaan terjadi selama atau setelah salinan dan hilang.

Jumlah halaman LOB yang dicadangkan setelah mengurangi ukuran imagedalam semua baris adalah sebagai berikut:

+ ------------------------------------------------- - + --------------------- + ------------------------- +
| Acara | lob_used_page_count | lob_reserved_page_count |
+ ------------------------------------------------- - + --------------------- + ------------------------- +
| Dimasukkan 10.000 baris dengan 100.000 byte data masing-masing | 135005 | 135017 |
| Diperbarui semua baris hingga 10.000 byte data gambar | 31251 | 135012 |
| Atur Kembali | 23687 | 25629 |
| Jatuhkan dan tambahkan kembali data gambar | 13485 | 13489 |
+ ------------------------------------------------- - + --------------------- + ------------------------- +
Martin Smith
sumber
1
Atau jika tabelnya besar maka BCP keluar data dan kemudian BULK INSERT kembali - selama jendela pemeliharaan.
Kin Shah
6

Mencoba

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

Ini membuat ulang indeks berkerumun, sehingga Anda akan membutuhkan ruang tambahan di database Anda untuk menyelesaikan operasi. Jika Anda tidak memiliki ruang tambahan karena disk Anda penuh, Anda mungkin dapat menambahkan file data baru ke database (pada disk yang berbeda) dan memindahkan tabel ke sana.

Mungkin juga indeks yang dikelompokkan ditentukan dengan FILLFACTOR kurang dari 100%. Memiliki faktor pengisian diatur ke, misalnya 66%, akan membuat 1/3 dari setiap halaman data kosong untuk digunakan di masa depan. Jika ini masalahnya, Anda bisa memodifikasi faktor pengisi menggunakanALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF, FILLFACTOR=100)

Jika Anda baru saja menjatuhkan bidang panjang variabel dari tabel, Anda juga bisa mencoba DBCC CLEANTABLE( Databasename, "MyTableName")

Buku online (BOL) memiliki artikel hebat tentang indeks pembangunan kembali di http://technet.microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx

Max Vernon
sumber
2

Pastikan mode pemulihan DB SIMPLE.

ubah kolom sebagai VARBINARY(MAX).

Kemudian coba salin data ke tabel yang sama sekali baru.

Periksa ukuran tabel baru menggunakan sp_spaceused "tablename". Jika Anda puas dengan ruang tabel yang tidak digunakan, maka periksa ruang database yang tidak digunakan menggunakan perintah yang sama tanpa menentukan nama tabel. Ruang itu masih dalam file database dan tidak dirilis ke OS.

Anda dapat menjatuhkan tabel asli dan mengganti nama tabel baru, atau melakukan hal yang sama lagi, dan menggunakan nama tabel asli jika Anda tidak percaya operasi penggantian nama, (Saya tidak percaya sepenuhnya).

Jika ini berhasil maka langkah terakhir mudah: Anda tahu cara mengecilkan file dan melepaskan ruang yang tidak digunakan.

Jika ada kunci asing, catat definisi mereka, lepaskan, lakukan tugas yang saya sebutkan di atas, dan buat ulang kunci asing sesudahnya. Tentu saja ini akan memakan waktu dan operasi ini harus dilakukan selama waktu libur. Seluruh tugas ini dapat dilakukan melalui skrip juga untuk membuatnya berjalan dalam semalam.

Anup Shah
sumber
1

Saya hanya akan membuat database baru dan menyalin datanya. Anda harus dapat menggunakan panduan impor / ekspor. (Jelas cadangan dan pemulihan akan menjaga masalah.) Periksa hasil pengimporan data. Jika semua terlihat bagus, ganti nama database asli dan kemudian ganti nama database baru dengan nama yang ingin Anda gunakan. (Saya selalu menunggu sedikit sebelum menjatuhkan yang asli, hanya untuk mengecek online.)

Untuk apa nilainya, kami juga telah mereklamasi ruang gumpalan dari database, jika mereka tidak terlalu besar, dengan langkah-langkah berikut. (Namun, karena Anda menggunakan SQL Server Express, Anda mungkin tidak memiliki ruang untuk mencoba ini.)

  1. Tambahkan file baru ke filegroup.
  2. Lari DBCC SHRINKFILE(file, EMPTYFILE). Karena Anda menyusutkan MDF, akhirnya ia akan gagal, karena metadata sistem tidak dapat dipindahkan. Namun, alokasi gumpalan kosong tidak dipindahkan.
  3. Lari DBCC SHRINKFILE(newfile,EMPTYFILE). Ini akan memindahkan data kembali, dikurangi ruang berlebih.
  4. Letakkan file baru (sekarang kosong) dari filegroup.

Ini menghilangkan gumpalan gumpalan. Saya harus menyebutkan bahwa kami telah menggunakan teknik ini terutama untuk membuat database yang sebagian besar kosong untuk menguji skrip upgrade.

RLF
sumber
-1

Atur kembali indeks berkerumun - bahwa seseorang memiliki data di node, jadi .... kemungkinan terfragmentasi.

TomTom
sumber
Saya sudah mencoba menjalankan: ALTER INDEX ALL ON [MyTableName] REORGANIZE;
DermFrench
3
Bangun kembali;) Tidak mengatur ulang.
TomTom