Вільний простір mdf та ldf не відповідає вільному простору бази даних


9

У SSMS я побачив властивості файлу, пов'язані з розміром, і знайшов нижче деталі для однієї бази даних. Тут значення не збігаються з іншими властивостями. Тут розмір mdf, ldf та загальний розмір збігаються з іншими значеннями під кожним вікном. Але наявний вільний простір mdf та ldf, якщо вони додані, то він не дорівнює наявному вільному простору, показаному у вікні скорочення бази даних та вільному простору, показаному у властивостях бази даних. Це справедливо для будь-якої бази даних. Чому так? Будь-хто може пояснити логіку цього?

Властивості бази даних:

Розмір: 91,31 Мб
простір: 13,40 МБ

Під файлами бази даних:

Розмір mdf: 17 Мб
Розмір ldf: 75 Мб

під скороченою базою даних:

На даний момент розмір: 91,31 Мб
Вільний простір: 13,40 МБ

під стислим файлом для файлу даних:

наразі розмір: 16,38 Мб
Вільний простір: 12,63 Мб

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

поточний розмір: 74,94 Мб
Вільний простір: 55,62 Мб

Відповіді:


11

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

Давайте зробимо деякі речі.

  1. Властивості бази даних та база даних зі зменшенням показують одне і те ж (не те, що ви коли-небудь повинні бути в інтерфейсі скорочення бази даних!).
  2. Властивості файлів бази даних показують 17 + 75 = 92, що з округленням перед додаванням, ймовірно, є таким же 91,31 в 1.
  3. Для виділеного простору скорочення для окремих файлів показує 16,38 + 74,94 = 91,32 - знову ж, ймовірно, деяке округлення там, інакше точно відповідає 1.
  4. Для доступного місця скорочення окремих файлів - це єдине місце, де я підозрюю реальну невідповідність, і це тому, що інтерфейс користувача не відповідає тому, звідки він отримує свої дані, і деякі з цих місць підпорядковуються кешування, що потребує оновлення DBCC.

Дозвольте мені ознайомитись із тим, як працюють ці різні діалоги для моєї локальної копії 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 Мб ніколи не було дійсно точним, оскільки це лише вимірювання загального розміру бази даних - кількості виділених сторінок, повністю ігноруючи журнал.

Якщо чесно, якщо ви хочете точно повідомити про місце, що використовується в базі даних, перестаньте використовувати користувальницькі інтерфейси миші, які виконують всілякі запити, щоб вирішити це, і перестаньте використовувати діалогові діалогові файли скорочення для отримання інформації. Вони, очевидно, є предметом несвіжих даних у певних випадках. Запустіть фактичний запит щодо джерела, якому ви можете довіряти. Ось що я віддаю перевагу:

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 думає про ці файли, тож ви можете пов’язатись з розрахунками, зробленими для визначення MB:

Розміри файлів у Windows

Наскільки точно все це повинно бути, звичайно, залежить від того, що ви збираєтеся робити з інформацією.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.