Tôi cần thu nhỏ cơ sở dữ liệu của mình - Tôi vừa giải phóng rất nhiều dung lượng


35

Câu hỏi này được hỏi dưới nhiều hình thức khác nhau ở đây nhưng câu hỏi rút lại thành:

Tôi biết thu hẹp một cơ sở dữ liệu là rủi ro. Trong trường hợp này, tôi đã xóa rất nhiều dữ liệu và tôi sẽ không bao giờ sử dụng lại.

  • Làm thế nào tôi có thể thu nhỏ cơ sở dữ liệu của tôi? Những tập tin nào tôi thu nhỏ?
  • Những cân nhắc của tôi nên là gì trong khi làm điều này?
  • Tôi có nên làm bất cứ điều gì sau?
  • Nếu nó là một cơ sở dữ liệu lớn thì sao? Tôi có thể thu nhỏ nó với gia số nhỏ hơn không?

2
Tôi đã vật lộn với điều này một thời gian trước đây: dba.stackexchange.com/questions/47 310/ Đổi Tôi đã cố gắng tóm tắt kinh nghiệm của mình trong câu trả lời của tôi
Csaba Toth

Câu trả lời:


30

Một số cảnh báo ban đầu:

  1. Nó thường được gọi là một thực tế tồi tệ nhất bao giờ thu nhỏ một cơ sở dữ liệu sản xuất hoặc dữ liệu tập tin (file Log là một vấn đề khác như câu hỏi này nói về). Tôi khuyên mọi người không nên thu nhỏ cơ sở dữ liệu của họ trong các bài đăng trên blog như thế này khi tôi nói về "đúng kích cỡ" và lập kế hoạch tốt. Tôi không đơn độc ở đó ( Paul Randal , Brent Ozar , chỉ để cung cấp thêm một vài liên kết). Thu hẹp lại một tập tin dữ liệu hoặc cơ sở dữ liệu phân mảnh chỉ số, là chậm và mất thời gian về tài nguyên của bạn, có thể là một cống trên hệ thống của bạn và chỉ là một điều xấu để làm, nói chung
  2. Trong trường hợp này, tất cả chúng ta đều biết rủi ro là có, chúng tôi đã sẵn sàng để đối phó với nó, nhưng chúng tôi đã giải phóng rất nhiều không gian mà chúng tôi biết rằng chúng tôi sẽ không bao giờ cần nữa. Vì vậy, trong loại trường hợp cụ thể này - thu nhỏ có rất nhiều ý nghĩa là một trong những lựa chọn của chúng tôi.

Nếu bạn đã đọc về những mối quan tâm và rủi ro và bạn vẫn cần thực hiện việc thu nhỏ này vì bạn đã giải phóng một lượng không gian đáng kể , hy vọng phần còn lại của câu trả lời này sẽ giúp bạn giải quyết. Nhưng hãy xem xét các rủi ro.

Có hai cách tiếp cận chính hai xem xét ở đây:

1.) Thu nhỏ Có, thực hiện thu nhỏ thực tế - Cân nhắc sử dụng DBCC SHRINKFILEthay vì DBCC SHRINKDATABASE, bạn có quyền kiểm soát nhiều hơn đối với những gì bị thu hẹp và làm thế nào. Điều này sẽ gây ra một số suy giảm hiệu suất chắc chắn - đó là một hoạt động lớn thực hiện rất nhiều IO. Bạn có khả năng có thể thoát khỏi các lần thu nhỏ lặp lại đến kích thước mục tiêu ngày càng nhỏ dần.

Đây là ví dụ "A.)" trong DBCC SHRINKFILEliên kết trên .. Một tệp dữ liệu đang được thu nhỏ thành kích thước mục tiêu 7MB trong ví dụ này. Định dạng này là một cách tốt để thu nhỏ nhiều lần khi cửa sổ thời gian chết của bạn cho phép. Tôi sẽ làm điều này trong thử nghiệm phát triển để xem hiệu suất trông như thế nào và mức tăng / thấp của bạn có thể tăng và để xác định thời gian dự kiến ​​trong sản xuất. Đây là một hoạt động trực tuyến - bạn có thể chạy nó với người dùng trong hệ thống truy cập cơ sở dữ liệu bị thu hẹp, nhưng sẽ có sự suy giảm hiệu suất, gần như được đảm bảo. Vì vậy, theo dõi và xem và xem những gì bạn đang làm với máy chủ, chọn một cửa sổ thời gian chết hoặc thời gian hoạt động nhẹ hơn, lý tưởng.

USE YourDatabase;
GO
DBCC SHRINKFILE (DataFile1, 7);
GO

Luôn nhớ: - mỗi khi bạn thu nhỏ lại, hãy phân mảnh các chỉ mục của mình và nên thực hiện xây dựng lại chỉ mục nếu bạn sẽ thu nhỏ lại trong một khoảng thời gian dài. Bây giờ bạn đang phải chịu chi phí đó mỗi lần nếu bạn không thể hoàn thành tất cả trong một cửa sổ.

2.) Cơ sở dữ liệu mới - Bạn có thể tạo cơ sở dữ liệu mới và di chuyển dữ liệu sang cơ sở dữ liệu đó. Bạn sẽ phải loại bỏ cơ sở dữ liệu trống và tất cả các khóa, chỉ mục, đối tượng, procs, hàm, v.v. và sau đó di chuyển dữ liệu sang nó. Bạn có thể viết các tập lệnh cho điều này hoặc bạn có thể sử dụng một công cụ như SQL Data So sánh từ Red Gate hoặc các nhà cung cấp khác có các công cụ tương tự. Đây là công việc thiết lập nhiều hơn về phía bạn, phát triển và thử nghiệm nhiều hơn, và tùy thuộc vào môi trường của bạn cũng có thể thổi bay cửa sổ thời gian chết của bạn nhưng một tùy chọn để xem xét.

Khi tôi buộc phải thu hẹp Cơ sở dữ liệu Nếu đây là môi trường của tôi, tôi sẽ tìm cách để lại một khoảng trắng công bằng / khổng lồ trong tệp dữ liệu vì tôi thích là một con heo đĩa và muốn chuẩn bị cho sự phát triển trong tương lai / bất ngờ. Vì vậy, tôi sẽ ổn khi trả lại không gian nếu chúng tôi chỉ xóa phần lớn không gian, nhưng tôi không bao giờ tin vào những câu nói "nhưng nó sẽ không bao giờ phát triển nữa" và vẫn để lại một khoảng trắng. Con đường tôi có thể đi với ( thở dài) là cách tiếp cận thu nhỏ nếu tôi có các cửa sổ thời gian chết nhỏ hơn và không muốn phát sinh sự phức tạp của việc tạo DB trống và di chuyển dữ liệu sang nó. Vì vậy, tôi sẽ thu nhỏ nó một loạt các lần tăng dần (dựa trên số lần tôi nghĩ rằng tôi cần dựa trên thử nghiệm của mình trong dev và kích thước mong muốn. Dần dần chọn kích thước tệp nhỏ hơn) và sau đó xây dựng lại các chỉ mục .. Và sau đó tôi Tôi không bao giờ nói với ai rằng tôi đã thu hẹp cơ sở dữ liệu của mình ;-)


1
Tôi sẽ thêm trường hợp đặc biệt rằng nếu bạn đã xóa rất nhiều dữ liệu từ một đống (đặc biệt là từ giữa đống), bạn sẽ không thể lấy lại khoảng trống đó cho đến khi bạn thêm một chỉ mục được nhóm vào đó (hy vọng là mãi mãi), và sau đó thả chỉ mục cụm sau (biến nó trở lại thành một đống). Tất nhiên nếu đống được cắt ngắn thường xuyên thì không có mối quan tâm. Nhưng vẫn đáng nói.
Jonathan Fite

Ai đó có thể giải thích hàm ý của NOTRUNCATE VÀ TRUNCATEONLY, rõ ràng trang sau không sắp xếp lại các trang và do đó không gây ra sự phân mảnh chỉ mục?
David Garcia

4
  1. Làm thế nào tôi có thể thu nhỏ cơ sở dữ liệu của tôi? Những tập tin nào tôi thu nhỏ? : Bạn có thể thu nhỏ các tệp riêng lẻ bằng DBCC SHRINKFILElệnh bạn đề cập. Nó phụ thuộc vào máy chủ của bạn có bao nhiêu tệp cơ sở dữ liệu của bạn. Một cơ sở dữ liệu đơn giản có một tệp cơ sở dữ liệu và một tệp nhật ký giao dịch.
  2. Những cân nhắc của tôi nên là gì trong khi làm điều này?: thu nhỏ ảnh hưởng đến phân mảnh chỉ mục của bạn, xem điểm thứ 3. Cũng lưu ý rằng bạn không muốn thu nhỏ tệp cơ sở dữ liệu đến kích thước tối thiểu có thể, bởi vì trong môi trường thế giới thực, dù sao nó cũng sẽ phát triển. Vì vậy, tôi sẽ điều chỉnh kích thước (trong ví dụ của bạn, bạn đã cho 7 megabyte) theo cách bạn sẽ để lại 10% -20% dung lượng trống trong tệp cơ sở dữ liệu, vì dù sao nó cũng sẽ được lấp đầy trong môi trường sản xuất và bạn có thể lưu một số chu kỳ tăng trưởng tự động theo cách đó. Vì vậy, số lượng thực tế cần tính toán cẩn thận. Cũng lưu ý rằng "giải phóng không gian lớn" mà bạn đã thực hiện sẽ làm tăng tệp nhật ký giao dịch thậm chí nhiều hơn dung lượng bạn có được trong tệp DB. Ngoài ra, mức tăng không gian thực tế bạn có thể trải nghiệm sẽ ít hơn những gì bạn mong đợi về mặt toán học! Vì vậy, giả sử bạn giải phóng toán học 12 hợp đồng biểu diễn,
  3. Tôi có nên làm bất cứ điều gì sau? : Như tôi đã đề cập trước đó, bạn muốn giới thiệu lại các chỉ mục mà sự phân mảnh bị biến dạng do kết quả của các thay đổi của SHRINK. Tôi chưa thử nghiệm đủ nếu bạn cần làm gì đặc biệt về thống kê truy vấn.
  4. Nếu nó là một cơ sở dữ liệu lớn thì sao? Tôi có thể thu nhỏ nó với gia số nhỏ hơn không? Hoạt động SHRINK có thể bị gián đoạn bất cứ lúc nào và bạn có thể tiếp tục sau đó. Tôi khuyên bạn nên thực hiện nó trên cơ sở dữ liệu ngoại tuyến nếu có thể. Bằng cách làm gián đoạn và tiếp tục, nó sẽ đi về phía trước cùng kích thước thu nhỏ. Về mặt lý thuyết, bạn có thể thu nhỏ theo mức tăng nhỏ hơn bằng cách chỉ định kích thước mục tiêu ít chặt chẽ hơn thay vì 7 megabyte, nhưng tôi sẽ nói rằng nếu bạn đang thực hiện nó trong sản xuất, thì hãy cứ thử đi. Như bạn thấy có vấn đề với sự phân mảnh chỉ số và tăng trưởng nhật ký giao dịch có thể. Vì vậy, tôi sẽ trải qua điều này chỉ một lần.

Tất cả chúng ta đều biết rằng không nên làm SHRINK thường xuyên. Tôi cố gắng bỏ qua tất cả các cảnh báo và từ chối mà bạn có thể biết bằng mọi cách. Sao lưu và không làm điều này ở nhà nếu có thể :)

Phần thưởng: trong môi trường nhân rộng nếu bạn thực hiện điều này trên cơ sở dữ liệu của nhà xuất bản, điều đó sẽ không khiến cơ sở dữ liệu thuê bao bị thu hẹp (có thể có vấn đề về kích thước vì chúng là phiên bản Express).

Cuối cùng, tập lệnh reindex của tôi:

USE YourDBName

DECLARE @TbName VARCHAR(255)
DECLARE @FullTbName VARCHAR(255)
DECLARE @IxName VARCHAR(255)
DECLARE myCursor CURSOR FOR
    SELECT OBJECT_NAME(dmi.object_id) AS TableName,i.name AS IndexName
    FROM sys.dm_db_index_physical_stats(14, NULL, NULL, NULL , 'LIMITED') dmi
    JOIN  sys.indexes i on dmi.object_id = i.object_id and dmi.index_id = i.index_id
    WHERE avg_fragmentation_in_percent > 30
    ORDER BY avg_fragmentation_in_percent
OPEN myCursor
FETCH NEXT FROM myCursor INTO @TbName, @ixName
WHILE @@FETCH_STATUS = 0
BEGIN
    IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = 'dba' AND TABLE_NAME = @TbName)
BEGIN
        SET @FullTbName = 'dba.' + @TbName
        IF (@ixName IS NULL)
        BEGIN
            PRINT 'Reindexing Table ' + @FullTbName
            DBCC DBREINDEX(@FullTbName, '', 0)
        END
        ELSE
        BEGIN
             PRINT 'Reindexing Table ' + @FullTbName + ', Index ' + @IxName
             DBCC DBREINDEX(@FullTbName, @IxName, 0)
        END
    END
    FETCH NEXT FROM myCursor INTO @TbName, @ixName
END
CLOSE myCursor
DEALLOCATE myCursor

Biến duy nhất trong số này là 14, có thể thu được bằng cách đưa ra select DB_ID('YourDBName')và tập lệnh giả định rằng bạn chỉ quan tâm đến các bảng trong lược đồ dba. *.


2
Đối với lưu ý xây dựng lại chỉ mục rằng DBREINDEX không được dùng trong SQL 2005. Thay vì tập lệnh khổng lồ có con trỏ, bạn chỉ có thể sử dụng: EXEC sp_MSForeachtable @ Command1 = "ALTER INDEX ALL ON? REBUILD" Hy vọng điều này sẽ giúp được ai đó.
KISS

2

Bạn đã nghe tất cả các cảnh báo về việc thu hẹp cơ sở dữ liệu và tất cả đều đúng. Nó sẽ phân đoạn các chỉ mục của bạn và nói chung, làm hỏng cơ sở dữ liệu của bạn và không nên được thực hiện trên một hệ thống sản xuất.

Nhưng, tôi thường làm như vậy hàng tuần khi tôi khôi phục bản sao lưu trên máy trạm do không gian trên ổ SSD của tôi. Tâm trí bạn, tôi đã không viết kịch bản này nhưng tìm thấy nó cách đây nhiều năm. Trên các cơ sở dữ liệu khác [250 GB], tôi đã tạo một gói SSIS sẽ chuyển các bảng mà tôi cần và sau đó tạo lại các chỉ mục cho cảm giác chỉ số rất mới mẻ đó.

DECLARE @DBFileName SYSNAME

DECLARE @TargetFreeMB INT

DECLARE @ShrinkIncrementMB INT

SET @DBFileName = 'Set Name of Database file to shrink'

-- Set Desired file free space in MB after shrink

SET @TargetFreeMB = 500
-- Set Increment to shrink file by in MB
SET @ShrinkIncrementMB = 100

SELECT [FileSizeMB] = convert(NUMERIC(10, 2),
round(a.size / 128., 2)),

[UsedSpaceMB] = convert(NUMERIC(10, 2),

round(fileproperty(a.NAME, 'SpaceUsed') / 128., 2)),

[UnusedSpaceMB] = convert(NUMERIC(10, 2),

round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2)),

[DBFileName] = a.NAME

FROM sysfiles a

DECLARE @sql VARCHAR(8000)
DECLARE @SizeMB INT
DECLARE @UsedMB INT

SELECT @SizeMB = size / 128.
FROM sysfiles
WHERE NAME = @DBFileName

SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

SELECT [StartFileSize] = @SizeMB
    ,[StartUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

WHILE @SizeMB > @UsedMB + @TargetFreeMB + @ShrinkIncrementMB

BEGIN
    SET @sql = 'dbcc shrinkfile ( ' + @DBFileName + ', ' + convert(VARCHAR(20), @SizeMB - @ShrinkIncrementMB) + ' ) '

    PRINT 'Start ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    EXEC (@sql)

    PRINT 'Done ' + @sql
    PRINT 'at ' + convert(VARCHAR(30), getdate(), 121)

    SELECT @SizeMB = size / 128.
    FROM sysfiles
    WHERE NAME = @DBFileName

    SELECT @UsedMB = fileproperty(@DBFileName, 'SpaceUsed') / 128.

    SELECT [FileSize] = @SizeMB
        ,[UsedSpace] = @UsedMB
        ,[DBFileName] = @DBFileName
END

SELECT [EndFileSize] = @SizeMB
    ,[EndUsedSpace] = @UsedMB
    ,[DBFileName] = @DBFileName

SELECT [FileSizeMB] = convert(NUMERIC(10, 2), round(a.size / 128., 2))

    ,[UsedSpaceMB] = convert(NUMERIC(10, 2), round(fileproperty a.NAME, 'SpaceUsed') / 128., 2))

,[UnusedSpaceMB] = convert(NUMERIC(10, 2), round((a.size - fileproperty(a.NAME, 'SpaceUsed')) / 128., 2))

,[DBFileName] = a.NAME

FROM sysfiles a

1

Báo giá dưới đây là trực tiếp từ Microsoft (áp dụng cho các phiên bản 2008-2016) và đưa ra hướng dẫn về việc khi nào và khi nào bạn nên sử dụng DBCC SHRINKFILE lệnh.

https://msdn.microsoft.com/en-us/l Library / ms189493.aspx

Thực hành tốt nhất

Xem xét các thông tin sau khi bạn định thu nhỏ tệp:

  • Một hoạt động thu nhỏ có hiệu quả nhất sau một hoạt động tạo ra nhiều không gian không sử dụng, chẳng hạn như bảng cắt ngắn hoặc hoạt động bảng thả.
  • Hầu hết các cơ sở dữ liệu yêu cầu một số không gian trống có sẵn cho các hoạt động hàng ngày. Nếu bạn thu nhỏ cơ sở dữ liệu nhiều lần và nhận thấy rằng kích thước cơ sở dữ liệu tăng trở lại, điều này cho thấy rằng không gian bị thu hẹp là cần thiết cho các hoạt động thông thường. Trong những trường hợp này, việc thu hẹp cơ sở dữ liệu nhiều lần là một hoạt động lãng phí.
  • Một hoạt động thu nhỏ không bảo tồn trạng thái phân mảnh của các chỉ mục trong cơ sở dữ liệu và thường làm tăng sự phân mảnh đến một mức độ. Đây là một lý do khác để không liên tục thu hẹp cơ sở dữ liệu.
  • Thu nhỏ nhiều tệp trong cùng một cơ sở dữ liệu theo tuần tự thay vì đồng thời. Sự tham gia vào các bảng hệ thống có thể gây ra sự chậm trễ do chặn.
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.