Це насправді не виглядає таким шаленим, але зауважте, що деякі діалоги інтерфейсу можуть не мати повністю оновленої інформації (саме тому у нас є такі речі, як DBCC UPDATEUSAGE ), і округлення також може бути задіяне в деяких із них розрахунки. Нарешті, діалогові вікна показують вам загальний простір для всієї бази даних , але нерозподілений простір обчислюється лише для файлів даних , а не для журналу.
Давайте зробимо деякі речі.
- Властивості бази даних та база даних зі зменшенням показують одне і те ж (не те, що ви коли-небудь повинні бути в інтерфейсі скорочення бази даних!).
- Властивості файлів бази даних показують 17 + 75 = 92, що з округленням перед додаванням, ймовірно, є таким же 91,31 в 1.
- Для виділеного простору скорочення для окремих файлів показує 16,38 + 74,94 = 91,32 - знову ж, ймовірно, деяке округлення там, інакше точно відповідає 1.
- Для доступного місця скорочення окремих файлів - це єдине місце, де я підозрюю реальну невідповідність, і це тому, що інтерфейс користувача не відповідає тому, звідки він отримує свої дані, і деякі з цих місць підпорядковуються кешування, що потребує оновлення 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:
Наскільки точно все це повинно бути, звичайно, залежить від того, що ви збираєтеся робити з інформацією.