Kullanılmayan Space SQL Server Tablosunu Boşaltma


11

SQL Server 2012 Express'te çok kullanılmayan alan içeren bir tablo var.

Veritabanında yer açmam gerekiyor.

| ADI | SATIRLAR | SAKLIDIR | VERİ | INDEX_SIZE | KULLANILMAMIŞ |
| ------------- | -------- | -------------- | ----------- --- | ------------ | -------------- |
| MyTableName | 158890 | 8928296 KB | 5760944 KB | 2248 KB | 3165104 KB |

3165104KB'yi serbest bırakmak için SQL'i nasıl edinebilirim?

Zaten denedim:

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) 

İşte tablo:

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

Yaptığımız tek şey ScanImage, her satırda çok daha küçük bir görüntüyle değiştirilir (bu kadar kullanılmayan alanın varlığıdır).

Yanıtlar:


10

Yaptığımız tek şey ScanImage, her satırda çok daha küçük bir görüntüyle değiştirilir (bu kadar kullanılmayan alanın varlığıdır)

Bazı deneyler yapmaktan en fazla alan etkili yöntem, ayırma birimini bırakmak ve yeniden doldurmak olacaktır (bunu yapmak için bir bakım pencereniz varsa).

Sorudaki tablo yapısı ile benim için en iyi alan azaltmayı sağlayan örnek kod:

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 

Her şey bir işlemde, bu nedenle makine çökerse geri alınır. Muhtemelen bazı hatalarla uğraşabilir veya en azından SET XACT_ABORT ON. Kullandığım SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;sırasında veya kopya sonra oluyor ve kaybolmasını herhangi eşzamanlı değişiklikleri önlemek için.

imageTüm satırlardaki bir boyutu küçüldükten sonra ayrılmış LOB sayfalarının sayısı aşağıdaki gibidir:

+ ------------------------------------------------- - + --------------------- + ------------------------- +
| Etkinlik | lob_used_page_count | lob_reserved_page_count |
+ ------------------------------------------------- - + --------------------- + ------------------------- +
| Her biri 100.000 bayt veriyle 10.000 satır eklendi | 135005 | 135017 |
| Tüm satırları 10.000 baytlık görüntü verilerine güncellendi | 31251 | 135012 |
| Yeniden Düzenleyin | 23687 | 25629 |
| Görüntü verilerini bırakma ve yeniden ekleme | 13485 | 13489 |
+ ------------------------------------------------- - + --------------------- + ------------------------- +

1
Veya tablo büyükse, BCP çıkış verisi ve ardından BULK INSERT - bakım penceresi sırasında.
Kin Shah

6

Deneyin

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

Bu, kümelenmiş dizini yeniden oluşturur, bu nedenle işlemin tamamlanması için veritabanınızda fazladan alana ihtiyacınız olacaktır. Diskiniz dolu olduğu için fazladan alanınız yoksa, veritabanına (farklı bir diskte) yeni bir veri dosyası ekleyebilir ve tabloyu ona taşıyabilirsiniz.

Kümelenmiş endeksin% 100'den daha az bir FILLFACTOR ile tanımlanması da mümkündür. Doldurma faktörünün, örneğin% 66 olarak ayarlanmış olması, ileride kullanılmak üzere her veri sayfasının 1 / 3'ünü boş bırakacaktır. Sorun buysa, dolgu faktörünü kullanarakALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF, FILLFACTOR=100)

Kısa bir süre önce tablodan değişken uzunluklu bir alan bıraktıysanız, DBCC CLEANTABLE( Databasename, "MyTableName")

Çevrimiçi kitaplar (BOL), http://technet.microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx adresinde dizin oluşturma ile ilgili harika bir makaleye sahiptir.


2

DB kurtarma modunun olduğundan emin olun SIMPLE.

sütunu olarak değiştirin VARBINARY(MAX).

Ardından, verileri tamamen yeni bir tabloya kopyalamayı deneyin.

Düğmesini kullanarak yeni tablo boyutunu kontrol edin sp_spaceused "tablename". Tablonun kullanılmayan alanından memnunsanız, tablo adını belirtmeden aynı komutu kullanarak veritabanının kullanılmayan alanını kontrol edin. Bu alan hala veritabanı dosyalarının içindedir ve işletim sistemine verilmez.

Orijinal tabloyu bırakıp yeni tabloyu yeniden adlandırabilir veya aynı şeyi tekrar yapabilir ve yeniden adlandırma işlemine güvenmiyorsanız orijinal tablo adını kullanabilirsiniz (Tamamen güvenmiyorum).

Bu işe yararsa, son adım kolaydır: Dosyaları nasıl küçülteceğinizi ve kullanılmayan alanı nasıl serbest bırakacağınızı bilirsiniz.

Yabancı anahtar varsa, tanımlarını kaydedin, bırakın, yukarıda bahsettiğim görevleri yerine getirin ve yabancı anahtarları daha sonra yeniden oluşturun. Tabii ki bu zaman alacaktır ve bu işlem kapalı zamanlarda yapılmalıdır. Bu görev, bir gecede çalışmasına izin vermek için komut dosyası aracılığıyla da yapılabilir.


1

Sadece yeni bir veritabanı oluşturup veriyi ona kopyalarım. Alma / verme sihirbazını kullanabilmeniz gerekir. (Açıkçası bir yedekleme ve geri yükleme sorunu devam ettirecektir.) Verileri içe aktarmanın sonuçlarını kontrol edin. Her şey yolundaysa orijinal veritabanını yeniden adlandırın ve sonra yeni veritabanını kullanmak istediğiniz adla yeniden adlandırın. (Orijinali bırakmadan önce her zaman biraz beklerim, sadece çevrimiçi bir çift kontrol için.)

Değer ne için, çok büyük değilse, aşağıdaki adımlarla veritabanlarından blob alanını geri aldık. (Ancak, SQL Server Express kullandığınız için bunu denemek için yeriniz olmayabilir.)

  1. Dosya grubuna yeni bir dosya ekleyin.
  2. Koş DBCC SHRINKFILE(file, EMPTYFILE). MDF'yi daralttığınız için, sistem meta verileri taşınamadığı için sonuçta başarısız olur. Ancak, boş damla ayırmaları taşınmaz.
  3. Koş DBCC SHRINKFILE(newfile,EMPTYFILE). Bu, eksi fazla alan eksi verileri geri taşıyacaktır.
  4. Yeni dosyayı (şimdi boş) dosya grubundan bırakın.

Bu damla şişmesini ortadan kaldırır. Bu tekniği öncelikle yükseltme komut dosyalarını test etmek için çoğunlukla boş bir veritabanı oluşturmak için kullandığımızı belirtmeliyim.


-1

Kümelenmiş dizini yeniden düzenleyin - biri düğümlerde veri içeriyor, bu yüzden ... muhtemelen parçalanmış.


Çalışmayı denedim: ALTER INDEX ALL [MyTableName] REORGANIZE;
DermFrench

3
Yeniden oluşturun;) Yeniden düzenlemeyin.
TomTom
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.