Dung lượng trống của mdf và ldf không khớp với không gian trống của cơ sở dữ liệu


9

Trong SSMS tôi đã thấy các thuộc tính liên quan đến kích thước tệp và được tìm thấy bên dưới chi tiết cho một cơ sở dữ liệu. Ở đây các giá trị không khớp với các thuộc tính khác. Ở đây kích thước của mdf, ldf và tổng kích thước khớp với các giá trị khác dưới mỗi cửa sổ. Nhưng không gian trống có sẵn của mdf và ldf nếu được thêm vào thì nó không bằng không gian trống có sẵn được hiển thị trong cửa sổ cơ sở dữ liệu thu nhỏ và không gian trống được hiển thị trong thuộc tính cơ sở dữ liệu. Điều này đúng với bất kỳ cơ sở dữ liệu nào. Tại sao nó như vậy? Xin vui lòng bất cứ ai có thể giải thích logic đằng sau này?

Theo thuộc tính cơ sở dữ liệu:

Dung lượng: 91,31 MB Dung lượng
trống: 13,40 MB

Theo đúng tệp cơ sở dữ liệu:

kích thước mdf: 17 MB
kích thước ldf: 75 MB

trong cơ sở dữ liệu thu nhỏ:

Kích thước được phân bổ hiện tại: 91,31 MB Dung lượng
trống hiện có: 13,40 MB

trong tệp thu nhỏ - cho tệp dữ liệu:

kích thước được phân bổ hiện tại: 16,38 MB Dung lượng
trống hiện có: 12,63 MB

trong tệp thu nhỏ - cho tệp nhật ký:

kích thước được phân bổ hiện tại: 74,94 MB Dung lượng
trống hiện có: 55,62 MB

Câu trả lời:


11

Điều này có vẻ không thực sự điên rồ, nhưng lưu ý rằng một số hộp thoại UI có thể không có thông tin cập nhật hoàn toàn (đây là lý do tại sao chúng ta có những thứ như DBCC UPDATEUSAGE ), và làm tròn cũng có thể liên quan đến một số trong số đó. tính toán. Cuối cùng, các hộp thoại hiển thị cho bạn tổng dung lượng cho toàn bộ cơ sở dữ liệu , nhưng không gian chưa phân bổ chỉ được tính cho các tệp dữ liệu , không phải nhật ký.

Hãy kết hợp một số thứ.

  1. Thuộc tính cơ sở dữ liệu và cơ sở dữ liệu thu nhỏ cho thấy điều tương tự (không phải là bạn nên có trong giao diện người dùng cơ sở dữ liệu thu nhỏ nào!).
  2. Thuộc tính tệp cơ sở dữ liệu hiển thị 17 + 75 = 92, với làm tròn trước khi thêm, có thể giống với 91,31 trong 1.
  3. Đối với không gian được phân bổ, thu nhỏ cho các tệp riêng lẻ hiển thị 16,38 + 74,94 = 91,32 - một lần nữa, có thể là một số làm tròn ở đó, nếu không thì khớp chính xác 1.
  4. Đối với không gian có sẵn, thu nhỏ cho các tệp riêng lẻ là nơi duy nhất tôi nghi ngờ có sự khác biệt thực sự và điều này là do UI không nhất quán về nơi lấy dữ liệu của nó và một số vị trí này phải tuân theo bộ đệm ẩn yêu cầu DBCC UPDATEUSAGE.

Hãy để tôi xem những hộp thoại khác nhau này chạy cho bản sao AdventureWorks2012 cục bộ của tôi (với các bảng nhất định được phóng to từ tập lệnh này ).

EXEC sp_spaceused;

Trả về này (chỉ kết quả đầu tiên):

database_size    unallocated space
-------------    -----------------
   1545.81 MB          6.67 MB

Về cơ bản chạy cái này, mà - tôi đã xác nhận qua dấu vết - gần như là cùng một truy vấn được thực hiện từ các thuộc tính cơ sở dữ liệu và hộp thoại thu nhỏ cơ sở dữ liệu (Tôi đã khắc các phần không liên quan từ thủ tục được lưu trữ và thêm một truy vấn bên ngoài để biểu diễn toán học SSMS hiện để hiển thị):

SELECT database_size = DbSize*8.0/1024 + LogSize*8.0/1024,
  [unallocated space] = (DbSize-SpaceUsed)*8.0/1024
FROM
(
  SELECT
    (SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df 
       WHERE df.type in ( 0, 2, 4 ) ) AS [DbSize],
    SUM(a.total_pages) AS [SpaceUsed],
    (SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df 
       WHERE df.type in (1, 3)) AS [LogSize]
  FROM sys.partitions p 
    join sys.allocation_units a on p.partition_id = a.container_id 
    left join sys.internal_tables it on p.object_id = it.object_id
) AS x;

Điều này trả về một trận đấu:

database_size    unallocated space
-------------    -----------------
    1545.8125             6.671875

Tất cả các hộp thoại hiển thị thông tin này một cách chính xác. Hộp thoại Thuộc tính cơ sở dữ liệu:

Hộp thoại Thuộc tính cơ sở dữ liệu

Hộp thoại Shrink Database:

Hộp thoại thu nhỏ cơ sở dữ liệu

Mặt khác , các hộp thoại thu nhỏ tệp chạy một truy vấn hơi khác (một lần nữa, đây được khắc / điều chỉnh cho thuận tiện):

SELECT SUBSTRING(name, CHARINDEX('_',name)+1, 4), 
  [Currently allocated space] = size/1024.0, 
  [Available free space] = (Size-UsedSpace)/1024.0
FROM
(
  SELECT s.name, 
    CAST(FILEPROPERTY(s.name, 'SpaceUsed') AS float)*CONVERT(float,8) AS [UsedSpace],
    s.size * CONVERT(float,8) AS [Size]
  FROM sys.database_files AS s
  WHERE (s.type IN (0,1))
) AS x;

Cũng lưu ý rằng, ngoài việc lấy dữ liệu kích thước từ một chức năng thay vì DMV, các vị từ chưa được cập nhật cho các loại tệp mới, như filestream / hekaton.

Các kết quả:

        Currently allocated space    Available free space
----    -------------------------    --------------------
Data                         1517                  7.9375 -- wrong
Log                       28.8125               25.671875 -- wrong

Vấn đề là FILEPROPERTY()chức năng, không được đảm bảo cập nhật (ngay cả sau khi DBCC UPDATEUSAGE(0);được chạy; bên dưới nhiều hơn). Điều này kết thúc với thông tin sai lệch này trên các hộp thoại:

Không gian đọc sai

Lưu ý, một lần nữa, 6,67 MB đó không bao giờ thực sự chính xác, vì điều này chỉ đo tổng kích thước cơ sở dữ liệu - số lượng trang được phân bổ, hoàn toàn không quan tâm đến nhật ký.

Thành thật mà nói, nếu bạn muốn báo cáo chính xác dung lượng được sử dụng trong cơ sở dữ liệu, hãy ngừng sử dụng UI chuột mickey chạy tất cả các loại truy vấn khác nhau để tìm ra điều này và ngừng sử dụng hộp thoại thu nhỏ tệp để truy xuất thông tin. Đây rõ ràng là đối tượng của vấn đề dữ liệu cũ trong một số trường hợp nhất định. Chạy một truy vấn thực tế đối với một nguồn mà bạn có thể tin tưởng. Đây là những gì tôi thích:

DECLARE @log_used DECIMAL(19,7);
CREATE TABLE #x(n SYSNAME, s DECIMAL(19,7), u DECIMAL(19,7), b BIT);
INSERT #x EXEC('DBCC SQLPERF(LogSpace);');
SELECT @log_used = u FROM #x WHERE n = DB_NAME();
DROP TABLE #x;

DECLARE @data_used DECIMAL(19,7);
SELECT @data_used = SUM(a.total_pages)*8/1024.0
FROM sys.partitions AS p 
INNER JOIN sys.allocation_units AS a 
ON p.[partition_id] = a.container_id;

;WITH x(t,s) AS
( 
  SELECT [type] = CASE 
    WHEN [type] IN (0,2,4) THEN 'data' ELSE 'log' END, 
    size*8/1024.0 FROM sys.database_files AS f
)
SELECT 
  file_type = t, 
  size = s,
  available = s-CASE t WHEN 'data' THEN @data_used ELSE @log_used END 
FROM x;

Truy vấn này trả về ba số trông rất quen thuộc và một số không nên:

file_type    size           available
---------    -----------    ----------
data         1517.000000     6.6718750
log            28.812500    17.9008512

Lưu ý rằng DBCC SQLPERF cũng hơi có vấn đề với việc sử dụng không gian, ví dụ như sau khi chạy:

DBCC UPDATEUSAGE(0);

Các truy vấn trên mang lại điều này thay vì:

file_type    size           available
---------    -----------    ----------
data         1517.000000     8.0781250
log            28.812500    17.8669481

sp_spaceusedbây giờ cũng mang lại các số trùng khớp ( 1545.81 MB / 8.08 MB), mặc dù - một lần nữa - đó chỉ là không gian có sẵn trong tệp dữ liệu và các hộp thoại thu nhỏ thuộc tính cơ sở dữ liệu và cơ sở dữ liệu cũng "chính xác" (nhưng hộp thoại tệp thu nhỏ vẫn còn lối thoát - FILEPROPERTY()dường như không bị ảnh hưởng bởi UPDATEUSAGEtất cả):

Hộp thoại Thuộc tính cơ sở dữ liệu sau khi cập nhật

Hộp thoại thu nhỏ cơ sở dữ liệu sau khi cập nhật

Hộp thoại thu nhỏ tệp dữ liệu sau khi cập nhật

Nhật ký thu nhỏ hộp thoại sau khi cập nhật

Ồ, và cũng có thể hiển thị những gì Windows Explorer nghĩ về các tệp này, vì vậy bạn có thể liên quan đến các tính toán được thực hiện để xác định MB:

Kích thước tệp trong Windows

Tất nhiên điều này chính xác đến mức nào, tất nhiên, phụ thuộc vào những gì bạn sẽ làm với thông tin.

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.