web-dev-qa-db-ja.com

mdfおよびldfの空き容量がデータベースの空き容量と一致しません

SSMSで、ファイルサイズに関連するプロパティを確認し、1つのデータベースの詳細を以下に示しました。ここで、値は他のプロパティと一致しません。ここで、mdf、ldf、および合計サイズのサイズは、各ウィンドウの下の他の値と一致します。ただし、mdfおよびldfの利用可能な空き領域が追加された場合、データベースの縮小ウィンドウに表示される利用可能な空き領域およびデータベースのプロパティに表示される空き領域とは異なります。これは、どのデータベースにも当てはまります。なぜそうなのですか?誰かがこの背後にある論理を説明できますか?

データベースのプロパティ:

サイズ:91.31 MB
空き容量:13.40 MB

データベースファイルのプロパティ:

mdfサイズ:17 MB
ldfサイズ:75 MB

縮小データベース:

現在割り当てられているサイズ:91.31 MB
利用可能な空き容量:13.40 MB

アンダーシュリンクファイル-データファイル用:

現在割り当てられているサイズ:16.38 MB
利用可能な空き容量:12.63 MB

アンダーシュリンクファイル-ログファイル:

現在割り当てられているサイズ:74.94 MB
利用可能な空き容量:55.62 MB

9
IT researcher

これはそれほど奇妙に思われるわけではありませんが、一部のUIダイアログには完全に最新の情報がない可能性があることに注意してください(これが DBCC UPDATEUSAGE などの理由です)。これらの計算の一部にも関与している。最後に、ダイアログにはデータベース全体の合計スペースが表示されますが、未割り当てスペースはデータファイルに対してのみ計算され、ログ。

いくつかを合体させましょう。

  1. データベースプロパティと縮小データベースは同じことを示します(とにかく縮小データベースUIにいる必要はありません!)。
  2. データベースファイルのプロパティは、17 + 75 = 92を示しています。これは、追加前の丸めにより、おそらく1の91.31と同じです。
  3. 割り当てられたスペースの場合、個々のファイルのシュリンクは16.38 + 74.94 = 91.32を示します-おそらく、おそらくそこで丸められますが、そうでなければ正確に1に一致します。
  4. 利用可能なスペースについては、個々のファイルの縮小は、実際の不一致が疑われる唯一の場所です。これは、UIがデータを取得する場所についてUIが一貫しておらず、これらの場所の一部がDBCC UPDATEUSAGEを必要とするキャッシュの対象となっているためです。

これらのさまざまなダイアログが、AdventureWorks2012のローカルコピーに対して実行される内容を見てみましょう(特定のテーブルは このスクリプト から拡大されています)。

_EXEC sp_spaceused;
_

これは(最初の結果セットのみ)を返します。

_database_size    unallocated space
-------------    -----------------
   1545.81 MB          6.67 MB
_

基本的にこれを実行します。これは、トレースで確認しましたが、データベースプロパティとデータベース縮小ダイアログから実行したクエリとほぼ同じです(ストアドプロシージャから関連性のない部分を切り分け、数学を表す外部クエリを追加しました) SSMSが表示のために行うこと):

_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;
_

これは一致を返します:

_database_size    unallocated space
-------------    -----------------
    1545.8125             6.671875
_

これらのダイアログはすべて、この情報を正しく表示します。データベースのプロパティダイアログ:

Database Properties dialog

[データベースの縮小]ダイアログ:

Shrink Database dialog

一方、shrinkfileダイアログは、少し異なるクエリを実行します(これも、便宜上、切り分け/適応されています)。

_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;
_

また、DMVの代わりに関数からサイズデータを取得することに加えて、述語はfilestream/hekatonのような新しいファイルタイプ用に更新されていません。

結果:

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

問題はFILEPROPERTY()関数であり、最新であることは保証されていません(DBCC UPDATEUSAGE(0);を実行した後でも、以下を参照)。これは、ダイアログに関する誤解を招く情報で終わります:

Wrong space available readings

ここでも、6.67 MBは実際には正確ではなかったことに注意してください。これは、データベースの合計サイズ(割り当てられたページ数)のみを測定しているため、ログを完全に無視しているためです。

正直なところ、データベースで使用されているスペースの正確なレポートが必要な場合は、さまざまな種類のクエリを実行するミッキーマウスUIの使用を停止してこれを把握し、情報を取得するための縮小ファイルダイアログの使用を停止します。これらは明らかに、特定のケースで古いデータの問題の影響を受けます。信頼できるソースに対して実際のクエリを実行します。これが私が好むものです:

_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;
_

このクエリは、見慣れたはずの3つの数値と、見慣れないはずの1つの数値を返します。

_file_type    size           available
---------    -----------    ----------
data         1517.000000     6.6718750
log            28.812500    17.9008512
_

DBCC SQLPERF も、実行後など、スペースの使用に関する問題が発生しやすいことに注意してください。

_DBCC UPDATEUSAGE(0);
_

上記のクエリは代わりにこれを生成します:

_file_type    size           available
---------    -----------    ----------
data         1517.000000     8.0781250
log            28.812500    17.8669481
_

_sp_spaceused_は、一致する数値も生成するようになりました(_1545.81 MB / 8.08 MB_)。ただし、これもdataファイル、およびデータベースプロパティとデータベースの縮小ダイアログも「正確」です(ただし、縮小ファイルのダイアログはまだずれています-FILEPROPERTY()UPDATEUSAGEの影響をまったく受けていないようです):

Database Properties dialog after updateusage

Database shrink dialog after updateusage

Data file shrink dialog after updateusage

Log file shrink dialog after updateusage

ああ、また、Windowsエクスプローラーがこれらのファイルをどのように考えているかも示しているので、MBを決定するために行われた計算に関連付けることができます。

File sizes in Windows

もちろん、これがどれほど正確である必要があるかは、情報をどのように処理するかによって異なります。

11
Aaron Bertrand