Saya memiliki tabel di database produksi yang memiliki ukuran 525 GB, di mana 383 GB tidak digunakan:
Saya ingin mendapatkan kembali sebagian ruang ini, tetapi, sebelum mengacaukan DB produksi, saya menguji beberapa strategi pada tabel yang sama dalam tes DB dengan lebih sedikit data. Tabel ini memiliki masalah serupa:
Beberapa informasi tentang tabel:
- Faktor pengisian diatur ke 0
- Ada sekitar 30 kolom
- Salah satu kolom adalah LOB jenis gambar, dan itu menyimpan file dengan ukuran mulai dari beberapa KB hingga beberapa ratus MB
- Tabel tidak memiliki indeks hipotetis yang terkait dengannya
Server menjalankan SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64). Basis data menggunakan SIMPLE
model pemulihan.
Beberapa hal yang saya coba:
- Membangun kembali indeks:
ALTER INDEX ALL ON dbo.MyTable REBUILD
. Ini memiliki dampak yang dapat diabaikan. - Reorganisasi indeks:
ALTER INDEX ALL ON dbo.MyTable REORGANIZE WITH(LOB_COMPACTION = ON)
. Ini memiliki dampak yang dapat diabaikan. Menyalin kolom LOB ke tabel lain, menjatuhkan kolom, menciptakan kembali kolom, dan menyalin data kembali (seperti yang diuraikan dalam posting ini: Membebaskan Ruang SQL Server Tabel yang Tidak Terpakai ). Ini mengurangi ruang yang tidak digunakan, tetapi sepertinya hanya mengubahnya menjadi ruang yang digunakan:
Menggunakan utilitas bcp untuk mengekspor tabel, memotongnya, dan memuatnya kembali (seperti diuraikan dalam posting ini: Cara membebaskan ruang yang tidak digunakan untuk sebuah tabel ). Ini juga mengurangi ruang yang tidak digunakan dan meningkatkan ruang yang digunakan ke tingkat yang sama seperti gambar di atas.
- Meskipun tidak disarankan, saya mencoba perintah DBCC SHRINKFILE dan DBCC SHRINKDATABASE, tetapi tidak berdampak pada ruang yang tidak digunakan.
- Berlari
DBCC CLEANTABLE('myDB', 'dbo.myTable')
tidak membuat perbedaan - Saya sudah mencoba semua hal di atas, sekaligus mempertahankan gambar dan tipe data teks dan setelah mengubah tipe data menjadi varbinary (max) dan varchar (max).
- Saya mencoba mengimpor data ke tabel baru dalam database baru, dan ini juga hanya mengubah ruang yang tidak digunakan menjadi ruang yang digunakan. Saya menguraikan detail dari upaya ini di pos ini .
Saya tidak ingin melakukan upaya ini pada DB produksi jika ini adalah hasil yang dapat saya harapkan, jadi:
- Mengapa ruang yang tidak digunakan baru saja dikonversi ke ruang yang digunakan setelah beberapa upaya ini? Saya merasa tidak memiliki pemahaman yang baik tentang apa yang terjadi di bawah tenda.
- Apakah ada hal lain yang bisa saya lakukan untuk mengurangi ruang yang tidak digunakan tanpa menambah ruang yang digunakan?
EDIT: Inilah laporan Penggunaan Disk dan skrip untuk tabel:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable](
[Column1] [int] NOT NULL,
[Column2] [int] NOT NULL,
[Column3] [int] NOT NULL,
[Column4] [bit] NOT NULL,
[Column5] [tinyint] NOT NULL,
[Column6] [datetime] NULL,
[Column7] [int] NOT NULL,
[Column8] [varchar](100) NULL,
[Column9] [varchar](256) NULL,
[Column10] [int] NULL,
[Column11] [image] NULL,
[Column12] [text] NULL,
[Column13] [varchar](100) NULL,
[Column14] [varchar](6) NULL,
[Column15] [int] NOT NULL,
[Column16] [bit] NOT NULL,
[Column17] [datetime] NULL,
[Column18] [varchar](50) NULL,
[Column19] [varchar](50) NULL,
[Column20] [varchar](60) NULL,
[Column21] [varchar](20) NULL,
[Column22] [varchar](120) NULL,
[Column23] [varchar](4) NULL,
[Column24] [varchar](75) NULL,
[Column25] [char](1) NULL,
[Column26] [varchar](50) NULL,
[Column27] [varchar](128) NULL,
[Column28] [varchar](50) NULL,
[Column29] [int] NULL,
[Column30] [text] NULL,
CONSTRAINT [PK] PRIMARY KEY CLUSTERED
(
[Column1] ASC,
[Column2] ASC,
[Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column4] DEFAULT (0) FOR [Column4]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column5] DEFAULT (0) FOR [Column5]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column15] DEFAULT (0) FOR [Column15]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column16] DEFAULT (0) FOR [Column16]
GO
Berikut adalah hasil dari mengeksekusi perintah dalam jawaban Max Vernon:
╔════════════╦═══════════╦════════════╦═════════════════╦══════════════════════╦════════════════════╗
║ TotalBytes ║ FreeBytes ║ TotalPages ║ TotalEmptyPages ║ PageBytesFreePercent ║ UnusedPagesPercent ║
╠════════════╬═══════════╬════════════╬═════════════════╬══════════════════════╬════════════════════╣
║ 9014280192║ 8653594624║ 1100376║ 997178 ║ 95.998700 ║ 90.621500 ║
╚════════════╩═══════════╩════════════╩═════════════════╩══════════════════════╩════════════════════╝
╔═════════════╦═══════════════════╦════════════════════╗
║ ObjectName ║ ReservedPageCount ║ UsedPageCount ║
╠═════════════╬═══════════════════╬════════════════════╣
║ dbo.MyTable ║ 5109090 ║ 2850245 ║
╚═════════════╩═══════════════════╩════════════════════╝
MEMPERBARUI:
Saya menjalankan yang berikut seperti yang disarankan oleh Max Vernon:
DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');
Dan inilah hasilnya:
DBCC UPDATEUSAGE: Usage counts updated for table 'MyTable' (index 'PK_MyTable', partition 1):
USED pages (LOB Data): changed from (568025) to (1019641) pages.
RSVD pages (LOB Data): changed from (1019761) to (1019763) pages.
Ini memperbarui penggunaan disk untuk tabel:
Dan keseluruhan penggunaan disk:
Jadi, sepertinya masalahnya adalah bahwa penggunaan disk yang dilacak oleh SQL Server menjadi sangat tidak sinkron dengan penggunaan disk yang sebenarnya. Saya akan mempertimbangkan masalah ini terselesaikan, tetapi saya akan tertarik untuk mengetahui mengapa hal ini terjadi sejak awal!
DBCC UPDATEUSAGE
memperbarui ruang yang tidak digunakan dan jumlah halaman yang tidak digunakan. Sepertinya penggunaan disk dan informasi halaman yang dilaporkan oleh SQL Server sangat tidak sinkron - Saya memperbarui posting saya dengan detailnya. Saya ingin tahu tentang bagaimana ini akan terjadi di tempat pertama, tetapi setidaknya masalah ditemukan. Terima kasih atas semua bantuan Anda, saya sangat menghargainya!