Уменьшить фрагментацию таблицы SQL Server без добавления / удаления кластерного индекса? - PullRequest
11 голосов
/ 26 июля 2010

У меня большая база данных (данные 90 ГБ, индексы 70 ГБ), которая медленно росла в течение последнего года, и рост / изменения вызвали большую внутреннюю фрагментацию не только индексов, но и самих таблиц.

Легко разрешить (большое количество) очень фрагментированные индексы - об этом позаботятся REORGANIZE или REBUILD, в зависимости от того, насколько они фрагментированы, - но единственный совет, который я могу найти при очистке фактической фрагментации таблицы, это добавить кластерный индекс к таблице. Я бы сразу же отбросил его, так как я не хочу, чтобы кластеризованный индекс в таблице развивался, но есть ли другой способ сделать это без кластерного индекса? Команда "DBCC", которая сделает это?

Спасибо за вашу помощь.

Ответы [ 5 ]

30 голосов
/ 03 ноября 2010

Задача

Давайте получим некоторую ясность, потому что это общая проблема, серьезная проблема для каждой компании, использующей SQL Server.

Эта проблема и необходимость CREATE CLUSTERED INDEX неправильно поняты.

Согласился, что иметь постоянный кластерный индекс лучше, чем не иметь его. Но это не главное, и в любом случае это приведет к длительному обсуждению, поэтому давайте отложим это и сосредоточимся на опубликованном вопросе.

Дело в том, что у вас есть существенная фрагментация в Heap . Вы продолжаете называть это «таблицей», но на физическом уровне хранения данных или уровне DataStructure такого нет. Таблица - это логическая концепция, а не физическая. Это коллекция физических DataStructures. Коллекция представляет собой одну из двух возможностей:

  • Heap
    плюс все некластеризованные индексы
    плюс текстовые / графические цепочки

  • или кластерный индекс
    (исключает кучу и один некластеризованный индекс)
    плюс все некластеризованные индексы
    плюс текстовые / графические цепочки.

Кучи плохо фрагментированы; чем больше разбросанных (случайных) вставок / удалений / обновлений, тем больше фрагментация.

Нет способа очистить кучу, как есть. MS не предоставляет услуги (другие поставщики делают).

Решение

Однако мы знаем, что Create Clustered Index полностью переписывает и переупорядочивает кучу. Поэтому метод (не хитрость) состоит в том, чтобы создать кластеризованный индекс только с целью дефрагментации кучи и затем отбросить ее. Вам нужно свободное место в БД table_size x 1.25.

Пока вы на нем, во что бы то ни стало, используйте FILLFACTOR, чтобы уменьшить будущую фрагментацию. Затем куча займет больше выделенного пространства, что позволит использовать в будущем обновления, удаления и расширения строк из-за обновлений.

Примечание

  1. Обратите внимание, что существует три уровня фрагментации; это касается только Уровня III, фрагментации внутри Кучи, которая вызвана Отсутствием кластерного индекса

  2. В качестве отдельной задачи в другое время вы можете рассмотреть возможность реализации постоянного кластерного индекса, который полностью устраняет фрагментацию ... но это отдельно от опубликованной проблемы.

Ответ на комментарий

SqlRyan:
Хотя это не дает мне волшебного решения моей проблемы, оно ясно показывает, что моя проблема является результатом ограничения SQL Server, и добавление кластеризованного индекса - единственный способ «дефрагментировать» кучу.

Не совсем. Я бы не назвал это «ограничением».

  1. Метод, который я дал для устранения фрагментации в куче, заключается в создании кластеризованного индекса и последующем его отбрасывании. Т.е. временно, единственной целью которого является правильное дробление.

  2. Реализация кластеризованного индекса в таблице (навсегда) является гораздо лучшим решением, поскольку она уменьшает в целом Фрагментацию (DataStructure все еще может быть фрагментирована, подробные сведения см. В ссылках ниже), которые гораздо меньше, чем фрагментация, которая происходит в куче.

    • Каждая таблица в реляционной базе данных (кроме таблиц "pipe" или "queue") должна иметь кластеризованный индекс, чтобы воспользоваться ее различными преимуществами.

    • Кластерный индекс должен находиться в столбцах, которые распространяют данные (избегая конфликтов INSERT), и никогда не должен индексироваться в монотонно увеличивающемся столбце, таком как ID записи 1 , что гарантирует горячую точку INSERT на последней странице.

1. Идентификаторы записей в каждом файле делают вашу «базу данных» нереляционной системой хранения записей, используя SQL просто для удобства. Такие файлы не имеют баз данных целостности, мощности или скорости реляционных данных.

Эндрю Хилл:
Не могли бы вы прокомментировать «Обратите внимание, что существует три уровня фрагментации; это касается только уровня III» - каковы два других уровня фрагментации?

В MS SQL и Sybase ASE существует три уровня фрагментации, а внутри каждого уровня несколько различных типов .Имейте в виду, что при работе с фрагментацией мы должны сосредоточиться на DataStructures, а не на таблицах (таблица, как описано выше, представляет собой набор DataStructures).Уровни:

  • Уровень I • Extra-DataStructure
    За пределами рассматриваемой DataStructure, в пределах или внутри базы данных.

  • Уровень II • DataStructure
    В соответствующей DataStructure, над страницами (на всех страницах)
    Этот уровень чаще всего используется администраторами баз данных.

  • Уровень III • Страница
    В соответствующей DataStructure, в пределах страниц

Эти ссылки предоставляют полную информацию о фрагментации.Они относятся к Sybase ASE, однако на структурном уровне информация относится к MS SQL.

Обратите внимание, что метод, который я дал, - это уровень II, он исправляет фрагментацию уровня II и III.

1 голос
/ 26 июля 2010

Вы утверждаете, что добавляете кластеризованный индекс, чтобы уменьшить фрагментацию таблицы, а затем немедленно ее отбросить.

Кластерный индекс удаляет фрагментацию путем сортировки по ключу кластера, но вы говорите, что этот ключ не будетвозможно для будущего использования.Возникает вопрос: зачем вообще выполнять дефрагментацию с использованием этого ключа?

Имеет смысл создать этот кластеризованный ключ и сохранить его, поскольку вы, очевидно, хотите / нуждаетесь в данных, отсортированных таким образом.Вы говорите, что изменения данных повлекут за собой штрафы за перемещение данных, которые не могут быть понесены;Вы думали о создании индекса с более низким FILLFACTOR, чем значение по умолчанию?В зависимости от модели изменения данных вы можете получить что-то от 80%.Тогда у вас будет 20% «неиспользуемого» пространства на страницу, но преимущество меньших разделений страницы при изменении значений кластеризованных ключей.

Может ли это помочь вам?

0 голосов
/ 12 февраля 2014

Проблема, о которой никто не говорит, - ФРАГМЕНТАЦИЯ ДАННЫХ ИЛИ ФАЙЛОВ УСТРОЙСТВА ЛОГА НА САМОМ ЖИДКОМ ПРИВОДЕ (-ях) !!Все говорят о фрагментации индексов и о том, как избежать / ограничить эту фрагментацию.

К вашему сведению: при создании базы данных вы указываете НАЧАЛЬНЫЙ размер .MDF вместе с тем, насколько он вырастет, когда потребуетсярасти.Вы делаете то же самое с файлом .LDF.НЕТ ГАРАНТИИ, ЧТО, КОГДА ДВЕ ФАЙЛЫ ВЫРАЩИВАЮТСЯ, ЧТО ДИСКОВОЕ ПРОСТРАНСТВО, ВЫДЕЛЕННОЕ ДЛЯ ДОПОЛНИТЕЛЬНОГО ПРОСТРАНСТВА ДИСКА, БУДЕТ ФИЗИЧЕСКИ ПРОДОЛЖИТЬ С СУЩЕСТВУЮЩИМ ПРОСТРАНСТВЕННЫМ ПРОСТРАНСТВОМ ДИСКА, РАСПРЕДЕЛЕННЫМ !!

Каждый раз, когда один из этих двух файлов устройств необходимо расширитьСуществует возможность фрагментации дискового пространства на жестком диске.Это означает, что головки на жестком диске должны работать усерднее (и занимать больше времени), чтобы перейти от одного раздела жесткого диска к другому разделу для доступа к необходимым данным в базе данных.Это аналогично покупке небольшого участка земли и строительству дома, который просто подходит для этой земли.Когда вам нужно расширить дом, у вас больше не будет земли, если вы не купите пустой участок по соседству - за исключением - что, если кто-то еще тем временем уже купил эту землю и построил на ней дом?Тогда вы не можете расширить свой дом.Единственная возможность - купить еще один участок земли в «окрестности» и построить на нем еще один дом.Возникает проблема: вы и двое ваших детей жили бы в доме A, а ваша жена и третий ребенок жили бы в доме B. Это было бы болезненно (если вы еще женаты).

РешениеЧтобы исправить эту ситуацию, нужно «купить гораздо больший участок земли, подобрать существующий дом (т.е. базу данных), переместить его на больший участок земли и затем расширить дом там».Хорошо - как ты это делаешь с базой данных?Сделайте полное резервное копирование, удалите базу данных (если у вас недостаточно свободного дискового пространства, чтобы сохранить как старую фрагментированную базу данных - на всякий случай - так и новую базу данных), создайте совершенно новую базу данных с большим выделенным начальным дисковым пространством (Мы не гарантируем, что операционная система обеспечит непрерывность запрошенного вами пространства), а затем восстановит базу данных в только что созданное новое пространство базы данных.Да, это трудная задача, но я не знаю ни одного программного обеспечения для автоматической дефрагментации диска, которое будет работать с файлами базы данных SQL.

0 голосов
/ 22 ноября 2010

Я понимаю вашу боль в том, что вы ограничены дизайном устаревшего дизайна.

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

В одном из моих старых приложений все данные были доступны через представления. Мне удалось изменить схему базовой таблицы, добавив столбец идентификаторов и кластеризованный индекс без влияния на приложение.

Другим недостатком наличия кучи является дополнительный ввод-вывод, связанный с любыми перенаправленными строками.

Я обнаружил, что статья ниже вступила в силу, когда меня спросили, есть ли какие-либо ДОКАЗАТЕЛЬСТВА, что нам нужен постоянно кластеризованный индекс в таблице

Эта статья от Microsoft

0 голосов
/ 21 ноября 2010

Вы можете компактировать кучу, запустив DBCC SHRINKFILE с NOTRUNCATE.

Судя по комментариям, вы не тестировали с постоянным кластерным индексом.

Чтобы представить это в перспективе, у нас есть база данных с 10 миллионами новых строк в день с кластеризованными индексами для всех таблиц.Удаленные «пробелы» будут удалены с помощью запланированного ALTER INDEX (а также прямых указателей / разбиений страниц).

Ваша таблица 12 ГБ может быть 2 ГБ после индексации: она просто имеет 12 ГБ, но также сильно фрагментирована.

...