Как это могло быть, когда мы перестроили кластерный индекс таблицы, в которой было около 15 ГБ данных, а размер данных сократился до 5 ГБ? Какие "данные" удаляются?
Размер данных я имею в виду столбец «данных» DBCC sp_spaceused
Перед перестройкой по кластерному индексу:
name rows reserved data index_size unused LEDGERJOURNALTRANS 43583730 39169656 KB 15857960 KB 22916496 KB 395200 KB
После перестроения по кластерному индексу:
name rows reserved data index_size unused LEDGERJOURNALTRANS 43583730 29076736 KB 5867048 KB 22880144 KB 329544 KB
TSQL для восстановления:
USE [DAX5TEST]
GO
ALTER INDEX [I_212RECID] ON [dbo].[LEDGERJOURNALTRANS] REBUILD PARTITION = ALL WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, ONLINE = ON, SORT_IN_TEMPDB = OFF, DATA_COMPRESSION = PAGE, FILLFACTOR = 85 )
GO
sql-server
clustered-index
Даниэль Бьорк
источник
источник
EXEC sp_spaceused
.ALTER INDEX
утверждение выглядит так, как будто оно было сгенерировано кодом (поскольку оно включает в себя множество параметров в настройках по умолчанию), поэтому я подозреваю, что оно было построено из существующих параметров индекса. Но вы правы: если сжатие не было включено в кластеризованном индексе до того, как он был запущен, это определенно объясняет большую часть сокращения объема данных. (снова: Даниэль, не могли бы вы подтвердить это так или иначе?)Ответы:
Когда таблица имеет кластеризованный индекс, индексом являются данные таблицы (в противном случае у вас есть таблица типов кучи). Перестроение кластеризованного индекса (фактически любой индекс, но пространство не будет считаться «данными» для некластеризованного индекса) приведет к объединению частично используемых страниц в более полную форму.
Когда вы вставляете данные в индекс (кластеризованный или иным образом) в конечные страницы порядка страниц, создаются по мере необходимости, и у вас всегда будет только одна частичная страница: одна в конце. Когда вы вводите данные не по порядку индексов, страницу нужно разделить, чтобы данные поместились в нужном месте: у вас получается две страницы, которые заполнены примерно наполовину, и новая строка переходит в одну из них. Со временем это может произойти много, потребляя изрядное количество дополнительного пространства, хотя в некоторой степени будущие вставки заполнят некоторые пробелы. Не листовые страницы также увидят аналогичный эффект, но реальные страницы данных имеют гораздо больший размер, чем они.
Также удаление может привести к частичным страницам. Если вы удалите все строки на странице, она будет считаться «неиспользованной», но если у нее останется одна или несколько строк данных, она все равно будет считаться используемой. Даже если на странице есть только одна строка, использующая 10 байтов, эта страница считается как 8192 байта в подсчете используемого пространства. Опять же, будущие вставки могут заполнить некоторые пробелы.
Для строк переменной длины обновления также могут иметь тот же эффект: по мере уменьшения строки она может оставлять на своей странице место, которое впоследствии будет непросто использовать повторно, а если строка на почти полной странице увеличивается в размерах, это может привести к разделению страницы. ,
SQL Server не тратит время на нормализацию данных путем изменения порядка использования страниц, пока не будет явно указано, например, порядок перестройки индекса, поскольку такие упражнения по сбору мусора могут стать кошмаром производительности.
Я подозреваю, что это то, что вы видите, хотя я бы сказал, что наличие достаточного пространства, выделенного примерно в 2,7 раза больше, чем абсолютно необходимо для данных, является особенно плохим случаем. Это может означать, что у вас есть что-то случайное в качестве одного из значимых ключей в индексе (возможно, столбец UUID), что означает, что новые строки вряд ли когда-либо будут добавлены в порядке индекса, и / или что в последнее время произошло значительное количество удалений.
Пример разделения страницы
Вставка в порядке индекса со строками фиксированной длины, четыре из которых помещаются на странице:
Теперь для добавления строк в индексном порядке (именно поэтому я использовал четные числа только выше): добавление
11
означало бы либо расширение этой второй страницы (это невозможно, поскольку они имеют фиксированный размер), перемещение всего выше 11 на одну (слишком дорого на большой индекс) или разделить страницу следующим образом:Отсюда добавление
13
и17
не приведет к разделению, так как в настоящее время есть место на соответствующих страницах:но добавление 03 будет:
Как вы можете видеть, после этих операций вставки у нас в настоящее время выделено 5 страниц данных, которые могут вместить в общей сложности 20 строк, но у нас есть только 14 строк («тратя» 30% пространства).
Перестройка с параметрами по умолчанию (см. Ниже о «коэффициент заполнения») приведет к:
сохранение одной страницы в этом простом примере. Легко увидеть, как удаление может иметь эффект, аналогичный вставкам вне индекса.
смягчение
Если вы ожидаете, что данные поступят в довольно случайном порядке по отношению к порядку индекса, вы можете использовать эту
FILLFACTOR
опцию при создании или перестройке индекса, чтобы указать SQL Server искусственно оставлять пробелы для последующего заполнения - сокращая разбиения страниц в долгосрочной перспективе, но занимая больше места изначально. Конечно, неправильное использование этого значения может сделать ситуацию намного хуже, чем улучшить ситуацию, поэтому обращайтесь с ней осторожно.Разделение страниц, особенно в кластеризованном индексе, может влиять на производительность для вставок / обновлений, поэтому
FILLFACTOR
иногда настраивается по этой причине вместо проблемы использования пространства в базах данных, которые видят большую активность записи (но для большинства приложений, где чтение перевешивает записи на несколько порядков вам лучше оставить коэффициент заполнения равным 100%, за исключением особых случаев, например, когда у вас есть индексы по столбцам с фактически случайным содержимым).Я предполагаю, что другие большие базы данных имеют аналогичную опцию, если вам нужен такой уровень контроля и в них.
Обновить
Что касается
ALTER INDEX
утверждения, добавленного к вопросу после того, как я начал печатать выше: я предполагаю, что параметры такие же, как при первом построении индекса (или последнем перестроении), но если нет, то параметр сжатия может быть очень значительным, если он был добавлен, время вокруг Также в этом утверждении коэффициент заполнения установлен на 85%, а не на 100%, поэтому каждая листовая страница будет ~ 15% пустой сразу после перестроения.источник
Когда вы перестраиваете индекс, он буквально помещает все данные на новые страницы. Я подозреваю, что произошло то, что вы удалили много данных до перестроения, например удалили столбец, обновили столбец переменной ширины, чтобы иметь меньше данных, изменили размер столбца фиксированной ширины или удалили много строк. Любая из этих операций может оставить много пустого пространства на страницах, которое не будет восстановлено до восстановления. Столбец «данные»
sp_spaceused
не измеряет фактические данные, а количество страниц 8K, используемых для хранения данных. Эти страницы теперь переполнены из-за перестройки, поэтому такой же объем данных умещается на меньшем количестве страниц.источник
sp_spaceused
Хранимая процедура не рассматривает общий culmulative размера строк в базе данных. Он сообщает о размере пространства, выделенного для хранения этих данных, в совокупном размере экстентов, выделенных для данных.Если доступно значительное свободное пространство, например, из множества удаленных строк, то перестроение кластеризованного индекса будет сжимать пространство в страницах и экстентах, чтобы быть более эффективным (то есть меньшим) по соображениям производительности.
Таким образом, никакие данные не должны были быть отброшены, но процесс восстановления сделал это свободное пространство, которое было встроено в страницы данных, снова доступным.
источник