Свободное место в mdf и ldf не совпадает со свободным пространством базы данных

9

В SSMS я видел свойства, связанные с размером файла, и нашел ниже детали для одной базы данных. Здесь значения не совпадают с другими свойствами. Здесь размер mdf, ldf и общий размер совпадает с другими значениями в каждом окне. Но Доступное свободное пространство mdf и ldf, если оно добавлено, оно не равно Доступному свободному пространству, показанному в окне уменьшенной базы данных, и свободному пространству, показанному в свойствах базы данных. Это верно для любой базы данных. Почему это так? Пожалуйста, кто-нибудь может объяснить логику этого?

Под свойствами базы данных:

Размер: 91,31 МБ Свободное
пространство: 13,40 МБ

Под свойствами файла базы данных:

Размер
файла : 17 МБ Размер файла: 75 МБ

при сжатой базе данных:

В настоящее время выделен размер: 91,31 МБ.
Свободное место: 13,40 МБ.

под сжатым файлом - для файла данных:

выделенный в настоящее время размер: 16,38 МБ.
Свободное место на диске: 12,63 МБ.

под сжатым файлом - для файла журнала:

выделенный в данный момент размер: 74,94 МБ.
Свободное место: 55,62 МБ.

IT исследователь
источник

Ответы:

11

На самом деле это не кажется таким уж сумасшедшим, но учтите, что некоторые диалоговые окна пользовательского интерфейса могут не содержать полностью обновленной информации (вот почему у нас есть такие вещи, как DBCC UPDATEUSAGE ), и в некоторых из них может быть задействовано округление. расчеты. Наконец, в диалоговых окнах отображается общее пространство для всей базы данных , но нераспределенное пространство рассчитывается только для файлов данных , а не для журнала.

Давайте объединим некоторые вещи.

  1. Свойства базы данных и сокращенная база данных показывают одно и то же (не то, что вы все равно должны быть в пользовательском интерфейсе сжатой базы данных!).
  2. Свойства файла базы данных показывают 17 + 75 = 92, что с округлением до сложения, вероятно, то же самое 91,31 в 1.
  3. Для выделенного пространства, сжатие для отдельных файлов показывает 16,38 + 74,94 = 91,32 - опять же, вероятно, некоторое округление там, в противном случае точно соответствует 1.
  4. Что касается доступного пространства, сжатие для отдельных файлов - это единственное место, где я подозреваю реальное расхождение, и это потому, что пользовательский интерфейс не согласуется с тем, где он получает свои данные, и некоторые из этих мест подвержены кешированию, что требует 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

Все эти диалоги показывают эту информацию правильно. Диалог свойств базы данных:

Диалог свойств базы данных

Диалог сокращения базы данных:

Диалог сокращения базы данных

С другой стороны, диалоги сжатых файлов запускают немного другой запрос (опять же, для удобства он вырезан / адаптирован):

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);запуска; подробнее ниже). Это заканчивается вводящей в заблуждение информацией о диалогах:

Неправильное пространство доступного чтения

Обратите внимание, опять же, что 6,67 МБ никогда не были действительно точными, так как это только измерение общего размера базы данных - количества выделенных страниц, без учета журнала.

Честно говоря, если вы хотите получать точные отчеты о пространстве, используемом в базе данных, прекратите использовать пользовательские интерфейсы mickey mouse, которые выполняют все виды различных запросов, чтобы выяснить это, и прекратите использовать диалоговые окна сжатых файлов для получения информации. Они явно подвержены устаревшим проблемам с данными в определенных случаях. Запустите реальный запрос к источнику, которому вы можете доверять. Вот что я предпочитаю:

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;

Этот запрос возвращает три числа, которые должны выглядеть очень знакомыми, и одно, которое не должно выглядеть так:

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), несмотря на то, - опять - таки - это только пространство , доступное в данном файле (ов), а свойство базы данных и термоусадочные баз данных диалоговых окна «точные» , а также (но термоусадочной файл Диалоги по - прежнему подальше - FILEPROPERTY()похоже не влияет UPDATEUSAGEвообще)

Диалог свойств базы данных после обновления

Диалог сокращения базы данных после обновления

Диалог сжатия файла данных после обновления

Диалог сокращения файла журнала после обновления

Да, и может также показать, что Windows Explorer думает об этих файлах, так что вы можете обратиться к вычислениям, сделанным для определения МБ:

Размеры файлов в Windows

Насколько точным должно быть все это, конечно, зависит от того, что вы собираетесь делать с информацией.

Аарон Бертран
источник