Размер базы данных - слишком большой MDF?

10

Я поддерживаю базу данных SQL Server 2005, на которой хранится приблизительно 2,9 ТБ данных (2 x 1,45 ТБ - у меня есть схема RAW и схема АНАЛИЗ, поэтому в основном две загруженные копии данных). Модель восстановления проста и .ldfнаходится на 6Gb.

По какой-то причине, .mdfэто 7,5 ТБ. Теперь в таблицах АНАЛИЗ может быть только 2-3 дополнительных столбца и не так много NVARCHAR(MAX)столбцов, которые, как я (возможно, ошибочно понял - пожалуйста, исправьте меня, если я ошибаюсь), могут вызывать дополнительное выделение пространства. Это после сокращения базы данных только сейчас - до этого было ~ 9Tb. Есть предположения?

И, пожалуйста, дайте мне знать, если у вас есть дополнительные вопросы - я очень плохо знаком с администрированием и оптимизацией баз данных (обычно я не выполняю эту часть работы :)).

Большое спасибо!

Андрия

Andrija_Bgd
источник
Спасибо, Марк. Как-нибудь я могу переместить этот вопрос туда или мне нужно переиздать?
Приветствия - как вы можете догадаться, я новичок здесь :)

Ответы:

11

В своих оценках размера вы учли количество места, занимаемое индексами? Кроме того, если у вас есть текстовые поля, которые заданы как многобайтовые ( 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 для получения более подробной информации), чтобы получить более подробную информацию, такую ​​как пространство, используемое каждым индексом.


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

  1. То, что ни для чего не выделено (это показано в первом наборе результатов sp_spaceusedбез указанного объекта)
  2. То, что выделено для объекта (зарезервировано), но не используется в данный момент (это показано в «неиспользованном» количестве в sp_spaceusedвыходных данных).
  3. Это заблокировано на частично использованных страницах (это будет выглядеть так, как будто все размещено на отдельных страницах, одна страница длиной 8192 байта). Это сложнее обнаружить / рассчитать. Это связано с сочетанием двух факторов:
    • Разделить страницы. По мере добавления данных вы часто получаете пустые страницы (механизм хранения всегда может нормализовать содержимое страницы, но это было бы очень неэффективно), а при удалении строк содержимое страницы не упаковывается автоматически (опять же, это может быть, но дополнительная Нагрузка ввода / вывода вообще далека от того)
    • Механизм хранения не будет разбивать строку на несколько страниц (вместе с размером страницы, откуда берется ограничение в 8 192 байта на строку). Если ваши строки имеют фиксированный размер и занимают 1100 байт каждая, то вы будете «тратить» не менее 492 байт каждого блока данных, выделенного для этой таблицы (7 строк занимают 7 700 байт, а 8-й не помещается, поэтому оставшиеся байты выигрывают ' не будет использоваться). Чем шире ряды, тем хуже это может быть. Таблицы / индексы со строками переменной длины (которые встречаются гораздо чаще, чем строки с полностью фиксированной длиной), как правило, лучше (но их труднее рассчитать).
      Еще одна оговорка здесь, большие объекты ( TEXTстолбцы,[N]VARCHAR(MAX) значения выше определенного размера и т. д.) поскольку они размещаются вне страницы, просто беря 8 байтов в данных основной строки для хранения указателя на данные в другом месте), что может нарушить ограничение 8192 байта на строку.

tl; dr: оценка ожидаемых размеров базы данных может быть гораздо более сложной, чем это изначально предполагалось.

Дэвид Спиллетт
источник
Дэвид - большое спасибо за подробный ответ! Я сейчас анализирую БД, и ответы как вас, так и Кеннета очень помогли мне понять факторы, влияющие на размер базы данных. Я всегда обеспокоен эффективностью (как в отношении приема, так и использования данных), и информация, которую вы, ребята, предоставили, была бесценной!
Andrija_Bgd
6

Попробуйте запустить sp_spaceusedсвою базу данных. В качестве примера возвращается:

reserved           data               index_size         unused
------------------ ------------------ ------------------ ------------------
6032 KB            2624 KB            1664 KB            1744 KB

Чтобы запустить его в базе данных, просто USEзапустите базу данных sp_spaceused.

Если он все еще показывает много неиспользуемого пространства, вы можете попробовать снова сжать. Иногда я нахожу, что это требует нескольких попыток. Также иногда я считаю, что лучше всего сжимать отдельный файл, а не базу данных в целом. Однако вы можете обнаружить, что у вас есть 2,9 ТБ данных и еще 4 + ТБ индексов, и в этом случае 7,5 ТБ вполне разумны. Если вы хотите почувствовать объем пространства (данные и индекс) каждой таблицы, вы также можете запустить ее sp_spaceusedна уровне таблицы. Вы можете запустить его для всех таблиц в базе данных, используя следующую команду:

EXEC sp_msforeachtable 'EXEC sp_spaceused [?];'

Хотя справедливое предупреждение sp_msforeachtable недокументировано, не поддерживается и, как известно, пропускает таблицы. С другой стороны, мне самому повезло с этим.

Все это говорит о том, что ваша база данных ДОЛЖНА иметь определенный процент свободного пространства в зависимости от вашего ожидаемого роста. По сути, вы хотите убедиться, что у вас есть место для роста от 6 месяцев до пары лет. Также вы захотите проверить свои autogrowthнастройки, чтобы убедиться, что они соответствуют вашей ситуации. В частности, учитывая размер вашей базы данных, вы НЕ хотите использовать% autogrowth.

Кеннет Фишер
источник
Спасибо! Я использовал sp_spaceused, и похоже, что фактические данные на самом деле занимают указанное количество места, как бы странно это ни звучало для меня, учитывая фактический размер загруженных плоских файлов ... Индексы малы (у меня нет Я не создал никаких дополнительных, так как они были бы скорее помехой, чем помощью в моем случае), поэтому я думаю, что это просто реальные таблицы, которые большие ... Спасибо за вашу помощь!
Andrija_Bgd
Базы данных занимают больше места, чем простые файлы. Существует определенное количество служебных данных для структур строк и таблиц и определенное количество отходов из-за структуры страницы.
Кеннет Фишер
-1

Используя SQL Management Studio, 1. Щелкните правой кнопкой мыши на базе данных, затем 2. Нажмите «Задачи» -> «Сжать» -> «Файлы».

Вы увидите диалоговое окно, которое показывает: В настоящее время выделенное пространство б. Доступное свободное пространство + (% свободного)

Если ваш% Free превышает 50%, вы можете рассмотреть возможность сжатия файла. Я видел этот удар целых 90%. Если я решаю сжать файл, я обычно устанавливаю его на 2 или 3 гигабайта больше, чем текущее выделенное пространство. Большинство моих баз данных меньше 50 гигов. Так что, если у вас гораздо больший файл, вы можете сделать его размером 10 гигов. Я обычно беспокоюсь только об уменьшении, если я собираюсь переместить базу данных на другой сервер, вы можете прочитать все о проблемах сокращения на любой странице sql.

Кларк Вера
источник