Tüm veritabanları için tüm dosyaları nasıl hızla küçültebilirim?


47

SQL Server'da (bu durumda 2008), bir örnek üzerindeki tüm veritabanları için hem günlük hem de veri olarak tüm dosyaları nasıl hızla küçültebilirim? SSMS'den geçip her birine sağ tıklayıp Görevler -> Küçült'ü seçebilirim, ancak daha hızlı bir şey arıyorum.

Bazı "Veritabanı oluştur" komut dosyaları yazdım ve varsayılanlar için büyüklükleri artırdıklarını unuttum ve bu projede bu dosyalar için ayrılmış çok fazla yere ihtiyaç duymadım.

Yanıtlar:


55

GUI'den "Görevler -> Küçült" işlevini yaptığınızda, aslında DBCC SHRINKDATABASEsahne arkasında bir komut verilir. Dene. İletişim kutusu açıldığında, "Tamam" düğmesini tıklamayın. Bunun yerine, "Komut Dosyası" düğmesini tıklayın. Komutu bir sorgu penceresinde göreceksiniz. Bunu sys.databases (master ve msdb dışında) sorgusuyla birleştirin ve tüm veritabanlarını daraltmak için bir komut dosyası oluşturabilirsiniz.

Örneğin (jcolebrand'ın yorumundan alınmıştır):

SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4;

Bu sorgunun çıktısını kopyalayın ve tüm dosyalarınızı daraltmak için çalıştırın.


1
Tamam, ben (çirkin ama does istediğini düşünüyorum sadece neyi ben bunu gerekir) SELECT 'USE [' + d.name + N']' + CHAR(13) + CHAR(10) + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) FROM sys.master_files mf JOIN sys.databases d ON mf.database_id = d.database_id WHERE d.database_id > 4Ama bu out endam bana yeni sorunu verdi. Başka bir soru göndermek için kapalı.
jcolebrand

Ciddi anlamda. @ Sandy'nin cevabını kontrol et. sp_MSForEachDB (ayrıca bir "masa" sproc da var) son derece faydalıdır
swasheck 14:12

3
Ve işte bunu okuyan herkese zorunlu hatırlatma: Veritabanınızı küçültmek tehlikelidir.
Nick Chammas,

1
Çevrimdışı DB filtreleme daha iyi yapardı. :-)
TiloBunt 21:14

1
@TiloBunt ile anlaşarak, tüm koşul NEREDE daha iyidir: d.database_id> 4 AND d.state_desc = 'ONLINE';
Mauro,

23

Tek bir satır sql ifadesine ne dersiniz?

Aşağıdaki sql ifadesini çalıştırmadan önce lütfen bu çok ilginç blog gönderisini okuyun .

EXEC sp_MSForEachDB 'DBCC SHRINKDATABASE (''?'' , 0)'

6
Düzgün çalışmayabilirse, tek bir kod satırı mutlaka daha iyi olmayabilir. Lütfen sp_msforeachdb veritabanlarını atlayıp sizi uyaramadığından, bu mesajları da okuyun: sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/… ve mssqltips.com/sqlservertip/2201/…
Aaron Bertrand

15

DBCC SHRINKDB (ve kuzeni SHRINKFILE) son derece yavaştır, çünkü bu kodda birçok tek iş parçacıklı yürütme oluyor.

Bir veritabanı dosyasını küçültmenin daha hızlı bir yolu şudur:

  • Veritabanına yeni bir dosya grubu ayır
  • Bu dosya grubunu olması gerektiği sp_spaceusedkadar büyük yapın ( ne kadar büyük olduğunu belirlemek için kullanın )
  • Tüm dizinleri bu yeni dosya grubuna yeniden oluştur
  • Eski dosya grubunu bırakın

Endeks yeniden yapılandırmaları büyük ölçüde paralel olduğundan, bu teknik genellikle veritabanının çok daha hızlı daralmasına neden olur. Tabii ki, işlem devam ederken yeni dosya grubu için biraz fazladan alana sahip olmanız gerekiyor. Ancak, yeni dosya grubunda yalnızca örnekteki en büyük dosya grubunu tutmak için yeterli alana ihtiyacınız vardır (devam ettikçe alanı geri kazanacağınız için).

Bu teknik aynı zamanda, süreç içindeki endekslerinizi birleştirmenin de faydası var.


Önemli bir kısmını unuttun. Dizinleri yeniden oluşturma, saklı yordamlar, görünümler, işlevler, eşanlamlılar, yığınlar vb. Gibi şeyler de dahil olmak üzere başka hiçbir şeyi taşımaz.
Jeff Moden

Ve bunlar umursayacağınız yer yok. Onlar da PRIMARY dosya
grubunda yer almak zorundalar,

13

İstediğiniz gibi sadece LOG'u küçültmek için küçük bir sorgu ayarladım:

set nocount on  
SELECT 
      'USE [' + d.name + N']' + CHAR(13) + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' + mf.name + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) 
FROM 
         sys.master_files mf 
    JOIN sys.databases d 
        ON mf.database_id = d.database_id 
WHERE d.database_id > 4 and mf.type_desc = 'LOG'

"hızlı bir şekilde tüm dosyaları, günlükleri ve verileri
daraltın

2
Bunu arıyordum ve cevabınızı gördüğümde ikiye katlamak üzereydim. Doğrudan cevap değil, ama benim durumum için ÇOK ilgili ve yerinde.
Gomibushi

2

Aşağıdaki kod, sistem dışı veritabanlarının bir listesini alın, veritabanını salt okunur olarak ayarlayın ve ardından dosyayı küçültün. Alanın her zaman sorun olduğu SQL Agent Job'u kullanarak birkaç SQL Server kutusunda bu kodu tuttum. Her hafta Sat / Sun gecelerinde, tüm veritabanlarını birkaç saat içinde çalıştırmaya ve küçültmeye başlar (veritabanlarının boyutuna bağlı olarak).

declare @db varchar(255)
declare c cursor for
select name from sys.databases where is_read_only=0 and state=0
  and name not in ('master','model','tempdb','msdb')
open c
fetch c into @db
while @@fetch_status=0
begin
  exec SP_dboption @db,'trunc. log on chkpt.','true' 
  DBCC shrinkdatabase (@db)
  fetch next from c into @db
end
close c
deallocate c

0

Master, model, msdb dışındaki tüm günlük dosyalarını küçültün:

EXEC sp_MSforeachdb '
DECLARE @sqlcommand nvarchar (500)
IF ''?'' NOT IN (''master'', ''model'', ''msdb'')
BEGIN
USE [?]
SELECT @sqlcommand = ''DBCC SHRINKFILE (N'''''' + 
name
FROM [sys].[database_files]
WHERE type_desc = ''LOG''
SELECT @sqlcommand = @sqlcommand + '''''' , 0)''
EXEC sp_executesql @sqlcommand
END'

0

Bu, yukarıdaki ifadeyi, SQL ifadeleri boyunca birer birer yineleme yapmak için bir imleç kullanarak genişletir. Emrah'ın cevabı kadar kısa değil, ancak imleç içindeki while döngüsü içinde ek mantığa izin veriyor.

SELECT 
    'USE [' 
    + databases.name + N']' 
    + CHAR(13) 
    + CHAR(10) 
    + 'DBCC SHRINKFILE (N''' 
    + masterFiles.name 
    + N''' , 0, TRUNCATEONLY)' 
    + CHAR(13) 
    + CHAR(10) 
    + CHAR(13) 
    + CHAR(10)                                                                  AS sqlCommand
INTO
    #shrinkCommands
FROM 
    [sys].[master_files] masterFiles 
    INNER JOIN [sys].[databases] databases ON masterFiles.database_id = databases.database_id 
WHERE 
    databases.database_id > 4; -- Exclude system DBs


DECLARE iterationCursor CURSOR

FOR
    SELECT 
        sqlCommand 
    FROM 
        #shrinkCommands

OPEN iterationCursor

DECLARE @sqlStatement varchar(max)

FETCH NEXT FROM iterationCursor INTO @sqlStatement

WHILE (@@FETCH_STATUS = 0)
BEGIN
    EXEC(@sqlStatement)
    FETCH NEXT FROM iterationCursor INTO @sqlStatement
END

-- Clean up
CLOSE iterationCursor
DEALLOCATE iterationCursor
DROP TABLE #shrinkCommands

0

Tüm veritabanları için SHRINKDBve SHRINKFILEdinamik olarak tekrarlayabiliriz :

while @DBID<=@MaxDBID
begin
  -- Used Dynamic SQL for all databases.
  Set @SQL ='Use '+@DBName+ ' '+Char(10)
  Set @SQL += 'DBCC SHRINKFILE('+@Filename+',5)' +Char(10)
  Set @SQL += 'DBCC SHRINKDATABASE('+@DBName+')'+Char(10)

  --#6 Increment DBid for looping over all databases
  Set @DBID = @DBID+1
  Select @DBName = DBName, @Filename=DBFileName from #DBNames where [dbid] = @DBID and type_Desc = 'LOG'
  Print (@SQL)
  Exec (@SQL)
end

Ayrıntıları bu makalede bulabilirsiniz .

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.