перестроить по кластерному индексу, почему размер данных сокращается?


10

Как это могло быть, когда мы перестроили кластерный индекс таблицы, в которой было около 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

Вы определяете размер данных по размеру файла?
JNK

Размер данных, я имею в виду столбец «data» в DBCC sp_spaceused
Даниэль Бьорк,

Это будет столбец «данных» EXEC sp_spaceused.
RLF

1
Каждый ли кто-то пропустил, что OP использует сжатие страницы = включено в своем скрипте перестройки, и я думаю, что это было не раньше. Даниэль, можешь подтвердить?
Шэнки

1
@Shanky: Это ALTER INDEXутверждение выглядит так, как будто оно было сгенерировано кодом (поскольку оно включает в себя множество параметров в настройках по умолчанию), поэтому я подозреваю, что оно было построено из существующих параметров индекса. Но вы правы: если сжатие не было включено в кластеризованном индексе до того, как он был запущен, это определенно объясняет большую часть сокращения объема данных. (снова: Даниэль, не могли бы вы подтвердить это так или иначе?)
Дэвид Спиллетт

Ответы:


16

Когда таблица имеет кластеризованный индекс, индексом являются данные таблицы (в противном случае у вас есть таблица типов кучи). Перестроение кластеризованного индекса (фактически любой индекс, но пространство не будет считаться «данными» для некластеризованного индекса) приведет к объединению частично используемых страниц в более полную форму.

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

Также удаление может привести к частичным страницам. Если вы удалите все строки на странице, она будет считаться «неиспользованной», но если у нее останется одна или несколько строк данных, она все равно будет считаться используемой. Даже если на странице есть только одна строка, использующая 10 байтов, эта страница считается как 8192 байта в подсчете используемого пространства. Опять же, будущие вставки могут заполнить некоторые пробелы.

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

SQL Server не тратит время на нормализацию данных путем изменения порядка использования страниц, пока не будет явно указано, например, порядок перестройки индекса, поскольку такие упражнения по сбору мусора могут стать кошмаром производительности.

Я подозреваю, что это то, что вы видите, хотя я бы сказал, что наличие достаточного пространства, выделенного примерно в 2,7 раза больше, чем абсолютно необходимо для данных, является особенно плохим случаем. Это может означать, что у вас есть что-то случайное в качестве одного из значимых ключей в индексе (возможно, столбец UUID), что означает, что новые строки вряд ли когда-либо будут добавлены в порядке индекса, и / или что в последнее время произошло значительное количество удалений.

Пример разделения страницы

Вставка в порядке индекса со строками фиксированной длины, четыре из которых помещаются на странице:

Start with one empty page: 
        [__|__|__|__]
Add the first item in index order:
        [00|__|__|__]
Add the next three
        [00|02|04|06]
Adding the next will result in a new page:
        [00|02|04|06] [08|__|__|__]
And so on...
        [00|02|04|06] [08|10|12|14] [16|18|__|__]

Теперь для добавления строк в индексном порядке (именно поэтому я использовал четные числа только выше): добавление 11означало бы либо расширение этой второй страницы (это невозможно, поскольку они имеют фиксированный размер), перемещение всего выше 11 на одну (слишком дорого на большой индекс) или разделить страницу следующим образом:

[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]

Отсюда добавление 13и 17не приведет к разделению, так как в настоящее время есть место на соответствующих страницах:

[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]

но добавление 03 будет:

[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]

Как вы можете видеть, после этих операций вставки у нас в настоящее время выделено 5 страниц данных, которые могут вместить в общей сложности 20 строк, но у нас есть только 14 строк («тратя» 30% пространства).

Перестройка с параметрами по умолчанию (см. Ниже о «коэффициент заполнения») приведет к:

[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]

сохранение одной страницы в этом простом примере. Легко увидеть, как удаление может иметь эффект, аналогичный вставкам вне индекса.

смягчение

Если вы ожидаете, что данные поступят в довольно случайном порядке по отношению к порядку индекса, вы можете использовать эту FILLFACTORопцию при создании или перестройке индекса, чтобы указать SQL Server искусственно оставлять пробелы для последующего заполнения - сокращая разбиения страниц в долгосрочной перспективе, но занимая больше места изначально. Конечно, неправильное использование этого значения может сделать ситуацию намного хуже, чем улучшить ситуацию, поэтому обращайтесь с ней осторожно.

Разделение страниц, особенно в кластеризованном индексе, может влиять на производительность для вставок / обновлений, поэтому FILLFACTORиногда настраивается по этой причине вместо проблемы использования пространства в базах данных, которые видят большую активность записи (но для большинства приложений, где чтение перевешивает записи на несколько порядков вам лучше оставить коэффициент заполнения равным 100%, за исключением особых случаев, например, когда у вас есть индексы по столбцам с фактически случайным содержимым).

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

Обновить

Что касается ALTER INDEXутверждения, добавленного к вопросу после того, как я начал печатать выше: я предполагаю, что параметры такие же, как при первом построении индекса (или последнем перестроении), но если нет, то параметр сжатия может быть очень значительным, если он был добавлен, время вокруг Также в этом утверждении коэффициент заполнения установлен на 85%, а не на 100%, поэтому каждая листовая страница будет ~ 15% пустой сразу после перестроения.


2
+1 Если коэффициент заполнения страницы меньше 100%, например, если коэффициент заполнения страницы был 50%, вновь перестроенный кластерный индекс ( таблица ) будет в два раза больше, чем если бы он был перестроен с коэффициентом заполнения 100%.
Макс Вернон,

6

Когда вы перестраиваете индекс, он буквально помещает все данные на новые страницы. Я подозреваю, что произошло то, что вы удалили много данных до перестроения, например удалили столбец, обновили столбец переменной ширины, чтобы иметь меньше данных, изменили размер столбца фиксированной ширины или удалили много строк. Любая из этих операций может оставить много пустого пространства на страницах, которое не будет восстановлено до восстановления. Столбец «данные» sp_spaceusedне измеряет фактические данные, а количество страниц 8K, используемых для хранения данных. Эти страницы теперь переполнены из-за перестройки, поэтому такой же объем данных умещается на меньшем количестве страниц.


5

sp_spaceusedХранимая процедура не рассматривает общий culmulative размера строк в базе данных. Он сообщает о размере пространства, выделенного для хранения этих данных, в совокупном размере экстентов, выделенных для данных.

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

Таким образом, никакие данные не должны были быть отброшены, но процесс восстановления сделал это свободное пространство, которое было встроено в страницы данных, снова доступным.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.