Làm cách nào để thu nhỏ tất cả các tệp một cách nhanh chóng cho tất cả các cơ sở dữ liệu?


47

Trong SQL Server (2008 trong trường hợp này), làm thế nào tôi có thể nhanh chóng thu nhỏ tất cả các tệp, cả nhật ký và dữ liệu, cho tất cả các cơ sở dữ liệu trên một ví dụ? Tôi có thể đi qua SSMS và nhấp chuột phải vào từng cái và chọn Nhiệm vụ -> Thu nhỏ, nhưng tôi đang tìm kiếm thứ gì đó nhanh hơn.

Tôi đã viết kịch bản một số tập lệnh "Tạo cơ sở dữ liệu" và quên rằng chúng có kích thước bóng cho mặc định và không cần nhiều không gian dành cho các tệp này trong dự án này.

Câu trả lời:


55

Khi bạn thực hiện "Nhiệm vụ -> Thu nhỏ" từ GUI, nó thực sự phát ra một DBCC SHRINKDATABASElệnh phía sau hậu trường. Thử nó. Khi hộp thoại xuất hiện, không nhấp vào nút "OK". Thay vào đó, nhấp vào nút "Script". Bạn sẽ thấy lệnh trong một cửa sổ truy vấn. Kết hợp điều đó với một truy vấn trên sys.database (bỏ qua master và msdb) và bạn có thể tạo một tập lệnh để thu nhỏ tất cả các cơ sở dữ liệu.

Ví dụ: (lấy từ nhận xét của jcolebrand):

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;

Sao chép đầu ra của truy vấn đó và chạy nó để thu nhỏ tất cả các tệp của bạn.


1
Ok, tôi nghĩ rằng tôi có những gì tôi muốn (xấu xí nhưng chỉ làm những gì tôi cần) 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 > 4Nhưng việc tìm ra điều đó đã cho tôi một vấn đề mới. Tắt để gửi một câu hỏi khác.
jcolebrand

Nghiêm túc. Kiểm tra câu trả lời của @ Sandy. sp_MSForEachDB (cũng có một sproc "bảng") cũng cực kỳ hữu ích
swasheck

3
Và đây là lời nhắc bắt buộc đối với tất cả những ai đang đọc điều này: Thu hẹp cơ sở dữ liệu của bạn là nguy hiểm.
Nick Chammas

1
lọc ra DB ngoại tuyến sẽ làm cho nó thậm chí còn tốt hơn. :-)
TiloBunt

1
Đồng ý với @TiloBunt, toàn bộ điều kiện tốt hơn là WHERE d.database_id> 4 AND d.state_desc = 'ONLINE';
Mauro

23

Làm thế nào về một dòng duy nhất của tuyên bố sql?

Xin vui lòng đọc này bài đăng blog rất thú vị trước khi thực hiện các câu lệnh SQL sau.

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

6
Một dòng mã không nhất thiết phải tốt hơn nếu nó có thể không hoạt động chính xác. Xin cũng đọc những bài viết, kể từ sp_msforeachdb có thể bỏ qua cơ sở dữ liệu và không cảnh báo bạn: sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/...mssqltips.com/sqlservertip/2201/...
Aaron Bertrand

15

DBCC SHRINKDB (và anh em họ của nó SHRINKFILE) cực kỳ chậm, bởi vì có rất nhiều thực thi luồng đơn đang diễn ra trong mã đó.

Một cách nhanh hơn nhiều để thu nhỏ tệp cơ sở dữ liệu là:

  • Phân bổ một nhóm mới vào cơ sở dữ liệu
  • Làm cho tập đoàn này lớn như nó phải có (sử dụng sp_spaceusedđể xác định mức độ lớn)
  • Xây dựng lại tất cả các chỉ mục cho nhóm mới này
  • Bỏ tập đoàn cũ

Bởi vì việc xây dựng lại chỉ mục là song song ồ ạt, kỹ thuật này thường dẫn đến việc thu hẹp cơ sở dữ liệu nhanh hơn nhiều. Tất nhiên, nó đòi hỏi bạn phải có thêm một chút không gian cho nhóm mới trong khi quá trình đang diễn ra. Tuy nhiên, bạn chỉ cần đủ không gian trong nhóm fileg mới để giữ nhóm filegroup lớn nhất trong trường hợp (vì bạn sẽ lấy lại không gian khi bạn đi cùng).

Kỹ thuật này cũng có thêm lợi ích của việc chống phân mảnh các chỉ mục của bạn trong quy trình.


Bạn đã quên một phần quan trọng. Việc xây dựng lại các chỉ mục sẽ không di chuyển bất cứ thứ gì khác, bao gồm những thứ như thủ tục được lưu trữ, chế độ xem, chức năng, từ đồng nghĩa, đống, v.v.
Jeff Moden

Và những người chiếm không có không gian mà bạn nên quan tâm. Họ cũng phải cư trú trong nhóm quay phim CHÍNH, bạn không thể thực sự di chuyển họ (và cũng không nên)
Thomas Kejser

13

Tôi đã điều chỉnh một chút truy vấn để chỉ thu nhỏ LOG khi được yêu cầu:

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'

"nhanh chóng thu nhỏ tất cả các tập tin, cả tin đăng nhập và dữ liệu"
Dezső

2
Tôi đang tìm kiếm điều này, và sắp sửa tăng gấp đôi bài đăng khi tôi thấy câu trả lời của bạn. Không trả lời trực tiếp, nhưng RẤT có liên quan và tại chỗ cho trường hợp của tôi.
Gomibushi 17/12/13

2

Mã dưới đây, lấy danh sách các cơ sở dữ liệu phi hệ thống, đặt cơ sở dữ liệu thành chỉ đọc và sau đó thu nhỏ tệp. Tôi đã giữ mã này trong một vài hộp SQL Server bằng SQL Agent Job, trong đó không gian luôn là một vấn đề. Vào đêm Sat / Sun mỗi tuần, nó bắt đầu chạy và thu nhỏ tất cả các cơ sở dữ liệu trong vòng vài giờ (tùy thuộc vào kích thước của cơ sở dữ liệu).

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

Thu nhỏ tất cả các tệp nhật ký ngoại trừ master, model, msdb:

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

Câu hỏi này mở rộng câu trả lời ở trên, sử dụng một con trỏ để lặp qua các câu lệnh SQL từng cái một. Nó không ngắn như câu trả lời của Emrah nhưng nó cho phép logic bổ sung trong vòng lặp while trong con trỏ ..

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

Chúng tôi có thể lặp lại SHRINKDBSHRINKFILEcho tất cả các cơ sở dữ liệu một cách linh hoạt:

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

Bạn có thể tìm thấy chi tiết trong bài viết này .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.