Чи враховували ви у своїх оцінках розміру кількість місця, що займає індекси? Крім того, якщо у вас є текстові поля, які встановлені як багатобайтові ( N[VAR]CHAR
а не [VAR]CHAR
), а вхідні файли UTF-8 або звичайний один байт на символ, то це підніме ваші вимоги до пам’яті до двох разів. Крім того, пам’ятайте, що якщо у вас є кластерний ключ / індекс в таблиці, розмір цього впливу впливає на всі інші індекси в таблиці, оскільки вони включають значення кластеризованого ключа для кожного рядка (так, щоб навести крайній приклад, якщо таблиця має NCHAR (10 ) введіть туди, де буде робитися INT, і це ваш кластерний ключ / індекс, ви не тільки використовуєте додаткові 16 байт на рядок на сторінках даних, а також витрачаєте 16 байт на рядок у кожному іншому індексі цієї таблиці ) .
Крім того, деякий простір буде виділено, але невикористаний, або тому, що двигун БД залишив деякий простір, виділений після видалення, щоб його можна було знову використовувати швидко для нових даних у цій таблиці, або тому, що шаблон вставки та видалення залишив для багатьох сторінок лише частину повний.
Ви можете запустити:
SELECT o.name
, SUM(ps.reserved_page_count)/128.0 AS ReservedMB
, SUM(ps.used_page_count)/128.0 AS UsedMB
, SUM(ps.reserved_page_count-ps.used_page_count)/128.0 AS DiffMB
FROM sys.objects o
JOIN sys.dm_db_partition_stats ps ON o.object_id = ps.object_id
WHERE OBJECTPROPERTYEX(o.object_id, 'IsMSShipped') = 0
GROUP BY o.name
ORDER BY SUM(ps.reserved_page_count) DESC
щоб швидко подивитися, які таблиці займають місце.
Також EXEC sp_spaceused
запуск у цій БД поверне два набори результатів. Перший перераховує загальний простір, що виділяється у файловій системі для файлів даних, і яка частина нерозподіленої, друга перераховує, скільки виділеного простору використовується для сторінок даних, для покажчикових сторінок або наразі не використовується.
sp_spaceused
також поверне простір, який використовується даним об'єктом, і ви можете зафіксувати це, щоб створити таблицю для аналізу:
-- TEMP TABLES FOR ANALYSIS
CREATE TABLE #tTables (sName NVARCHAR(MAX), iRows BIGINT, iReservedKB BIGINT, iDataKB BIGINT, iIndexKB BIGINT, iUnusedKB BIGINT)
CREATE TABLE #tTmp (sName NVARCHAR(MAX), iRows BIGINT, sReservedKB NVARCHAR(MAX), sDataKB NVARCHAR(MAX), sIndexKB NVARCHAR(MAX), sUnusedKB NVARCHAR(MAX))
-- COLLECT SPACE USE PER TABLE
EXEC sp_msforeachtable 'INSERT #tTmp EXEC sp_spaceused [?];'
-- CONVERT NUMBER-AS-TEXT COLUMNS TO NUMBER TYPES FOR EASIER ANALYSIS
INSERT #tTables SELECT sName, iRows
, CAST(REPLACE(sReservedKB, ' KB', '') AS BIGINT)
, CAST(REPLACE(sDataKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sIndexKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sUnusedKB , ' KB', '') AS BIGINT)
FROM #tTmp
DROP TABLE #tTmp
-- DO SOME ANALYSIS
SELECT sName='TOTALS', iRows=SUM(iRows), iReservedKB=SUM(iReservedKB), iDataKB=SUM(iDataKB), iIndexKB=SUM(iIndexKB), iUnusedKB=SUM(iUnusedKB) FROM #tTables ORDER BY sName
SELECT * FROM #tTables ORDER BY iReservedKB DESC
-- CLEAN UP
DROP TABLE #tTables
Вищевказаний код виведе всі розміри таблиці в один список плюс один рядок для підсумків. При необхідності ви можете використовувати різні види системи (як sys.objects
і sys.dm_db_partition_stats
використовувані в першому запиті вище, див http://technet.microsoft.com/en-us/library/ms177862.aspx для набагато більш детально) , щоб отримати більш детальну інформацію , наприклад, простір, що використовується кожним індексом.
У файлі даних є три класи невикористаного простору:
- Те, що не виділено ні на що (це показує в першому наборі результатів
sp_spaceused
з не вказаним об'єктом)
- Те, що виділено об'єкту (зарезервовано), але в даний час не використовується (це відображається у "невикористаному" рахунку у
sp_spaceused
вихідних даних.
- Що заблоковано на сторінках, що використовуються частково (це, схоже, буде використано, оскільки все розподіляється по одних фрагментах сторінок, одна сторінка має довжину 8,192 байт). Це важче виявити / обчислити. Це пов'язано з поєднанням двох факторів:
- Розділити сторінки. Коли дані додаються, ви часто стикаєтесь із частиною порожніх сторінок (механізм зберігання даних завжди може нормалізувати вміст сторінки, але це було б дуже неефективно), і як видалені рядки вміст сторінки автоматично не упаковується (знову це може бути, але додатково Навантаження вводу / виводу, як правило, далеко не варто).
- Двигун пам’яті не розділить рядок на кілька сторінок (це разом із розміром сторінки, звідки походить обмеження 8,192 байт на рядок). Якщо ваші рядки мають фіксований розмір і беруть по 1100 байт, тоді ви збираєтеся "витрачати" щонайменше 492 байти кожного блоку даних, виділеного до цієї таблиці (7 рядків займають 7 700 байт, а 8-й не підходить, тому решта байт виграли " t використовувати). Чим ширші рядки, тим гірше це може бути. Таблиці / покажчики з рядками змінної довжини (які набагато частіші, ніж цілком фіксованої довжини), як правило, краще (але обчислення не так просто).
Ще один застереження тут - великі об'єкти ( TEXT
стовпці,[N]VARCHAR(MAX)
значення вище певного розміру тощо), оскільки вони розміщуються поза сторінкою, просто беручи 8 байт у даних основного рядка, щоб утримувати вказівник на дані в інших місцях), таким чином, можна порушити 8,192 байт на рядок-межа.
tl; dr: Оцінка очікуваних розмірів баз даних може бути значно більше, ніж це прийнято вважати спочатку.