Какова цель PAD_INDEX в этом ограничении SQL Server? - PullRequest
37 голосов
/ 28 июля 2011

У меня есть следующее ограничение, применяемое к одной из моих таблиц, но я не знаю, что означает PAD_INDEX.

Может ли кто-нибудь просветить меня?

CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED 
(
    [EmployeeId] ASC
) WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
        ^--------------^
         this part here

Ответы [ 5 ]

57 голосов
/ 28 июля 2011

Индексом в SQL Server является B-Tree

  • FILLFACTOR применяется к нижнему слою
    Это листовой узел / слой данных на рисунке ниже

  • PAD_INDEX ON означает «Применить FILLFACTOR ко всем слоям»
    Это промежуточные уровни на рисунке ниже (между корнем и данными)

Это означает, что PAD_INDEX полезен, только если установлен FILLFACTOR. FILLFACTOR определяет, сколько свободного места на странице данных (примерно)

Изображение из MSDN :

B-Tree structure

50 голосов
/ 03 июля 2015

По сути, вы устанавливаете PAD_INDEX = ON, если вы ожидаете много случайных изменений индекса регулярно.

Это помогает избежать разбиения страницы индекса.

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

20 голосов
/ 28 июля 2011

С MSDN :

PAD_INDEX = {ON |OFF}

Указывает заполнение индекса.По умолчанию установлено значение OFF.

ON: процент свободного пространства, указанный с помощью fillfactor, применяется к страницам индекса промежуточного уровня.

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

Опция PAD_INDEX полезна, только когда FILLFACTORуказано, потому что PAD_INDEX использует процент, указанный в FILLFACTOR.Если процентное значение, указанное для FILLFACTOR, недостаточно велико, чтобы разрешить одну строку, компонент Database Engine внутренне переопределяет процент, чтобы обеспечить минимальное значение.Число строк на странице промежуточного индекса никогда не бывает меньше двух, независимо от того, насколько низко значение fillfactor.

В обратно совместимом синтаксисе WITH PAD_INDEX эквивалентно WITH PAD_INDEX = ON.

6 голосов
/ 26 октября 2018

Это на самом деле очень сложный предмет. Включение PAD_INDEX может оказать существенное влияние на производительность чтения и нагрузку на память в больших таблицах. Чем больше стол, тем больше эффект. Как правило, я бы сказал, что вы хотите оставить все как есть, если вы не попадаете в категории НЕОБЫЧНЫЕ. Затем внимательно следуйте этому совету . Как показано в примере ниже, настройка FILLFACTOR при включенном PAD_INDEX может иметь экспоненциальный эффект, который необходимо тщательно сбалансировать.

  1. PAD_INDEX ВСЕГДА оказывает вредное влияние на чтение! Чем ниже значение FILLFACTOR, тем больше эффект, поэтому вам нужно обратить пристальное внимание на значение FILLFACTOR при его включении. На больших столах вы, по сути, перестаете думать о FILLFACTOR с точки зрения уменьшения расщепления листьев и начинаете думать о его влиянии на промежуточное раздувание по сравнению с промежуточными расколами .
  2. PAD_INDEX редко оказывает полезное влияние на индексы с количеством строк менее 100 000, и НИКОГДА не оказывает положительного влияния на индексы, охватывающие столбцы идентификаторов или типа вставки, когда вставки всегда находятся в конце таблицы.
  3. Из вышесказанного вы должны увидеть, что если вы включаете PAD_INDEX, вы должны тщательно сбалансировать отрицательные эффекты с положительными.

Практические правила : PAD_INDEX редко используется для некластеризованных индексов, если они не достаточно широки, для кластеризованных индексов очень узких таблиц или для таблиц, которые имеют строки менее 100 КБ, если вставки не являются сильно кластеризованными и даже тогда это может быть сомнительным.

Вы ДОЛЖНЫ понять, как это работает: Когда вы вставляете в указатель, строка должна вписываться в листовой блок, который содержит соответствующий диапазон клавиш. Кластерные индексы обычно имеют гораздо более широкие строки, чем некластеризованные индексы, поэтому их листовые блоки содержат меньше строк. FillFactor создает пространство для новых строк в листе, но в случае очень широких рядов или большого объема вставок, которые сгруппированы вместе, а не равномерно распределены, зачастую нецелесообразно или невозможно создать достаточную слабину (заполнение в 1 процент), чтобы предотвратить разбиения.

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

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

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

В большинстве случаев разделением можно управлять с помощью FILLFACTOR. Большие проблемы разделения возникают с шаблонами вставки, которые фактически гарантируют, что у вас не будет достаточно свободного места, а включение PAD_INDEX помогает облегчить это, предоставляя пространство на более глубоких уровнях, поэтому, когда происходит разделение, вы с меньшей вероятностью подвергнетесь многоуровневым разделениям.

Пример дела

У меня есть таблица клиентов с 100К строк. В любой день около 5% моих клиентов будут активны. У меня есть таблица, которая записывает активность клиентов по времени. В среднем клиент выполняет 20 действий, а описание занимает в среднем 1 КБ. Итак, я собираю 100 МБ данных, и давайте предположим, что у меня уже есть год в таблице - так что 36 ГБ.

В таблице есть вставки строк размером 1 Кбайт с customer_number и insert_time (в этом порядке) для ключевых столбцов. Очевидно, что средний клиент будет разбивать листовой блок размером 8 КБ несколько раз, вставляя ожидаемые 20 строк, потому что каждая строка будет вставляться сразу после предыдущей строки в том же блоке, пока не будет разбита, разбита и разбита (поэтому нужно рассматривать кучу только с некластеризованными индексы ...). Если промежуточному блоку, указывающему на соответствующий лист, не хватает места как минимум для 4 рядов (в действительности, вероятно, 8, но ...), промежуточный блок необходимо будет разделить. Учитывая, что ключ этого примера занимает 22 байта, промежуточный блок может содержать 367 записей. Это означает, что мне нужно 6% свободного места в промежуточном блоке или заполнение 94% для хранения 4 записей.

Обратите внимание, что даже 1% FILLFACTOR не остановит разбиение блоков листьев, поскольку блок может содержать только 8 строк. Установка FILLFACTOR в значение 80% позволит добавить только 1 строку до разбиения листа, но добавит более 800 байтов свободного пространства на промежуточный блок, если включен PAD_INDEX. Это ~ 800 пустых байтов для КАЖДОГО промежуточного блока, когда мне нужно только 88.

Это действительно важно! : Итак, если у меня уже есть 36M строк в таблице, использование 80% означает 294 строки на промежуточный блок, то есть 122K блоков, то есть я вставил 98MB в свой промежуточный блок структура, при которой 94% позволяют разместить 345 строк на блок, так что промежуточных блоков всего 104K (да, для простоты я опускаю нижние уровни). Добавление 88 байтов к каждому из блоков 104 КБ добавляет всего 9,2 МБ, а не 98 МБ.

Теперь учтите, что только 5% моих клиентов что-то сделали. Некоторые делали более 20 вещей, а некоторые меньше, поэтому некоторые блоки в любом случае разделялись, и поскольку для хранения строк индекса дня (100k / 8 * 22) фактически требовалось всего 275 КБ, лучшим случаем является то, что только 8,9 МБ из моих 9,2 МБ были мертвыми. , Если важна профилактика разбиения, она стоит 9 Мб, но я бы подумал о 98 Мб.

Так что, включив PAD_INDEX, я должен полностью отказаться от контроля листовых сплитов и перейти к контролю промежуточных сплитов.

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

0 голосов
/ 08 ноября 2018

@ bielawski Вы описываете только случаи, когда PAD_INDEX = ON и FILLFACTOR находятся в диапазоне от 1 до 99. Что вы думаете о наборе PAD_INDEX = ON и FILLFACTOR = 0 или 100 в случае, если я вставляю упорядоченные строки, которые всегда будут новее, чем предыдущиеодин.

CREATE CLUSTERED INDEX [IX_z_arch_export_dzienny_pre] ON [dbo].[z_arch_export_daily_pre]
(
    [Date] ASC,
    [Object Code] ASC,
    [From date] ASC,
    [Person_role] ASC,
    [Departure] ASC,
    [Room code] ASC,
    [period_7_14] ASC
)WITH (PAD_INDEX = ON, FILLFACTOR=100)


insert into z_arch_export_daily_pre
select * from export_daily_pre
order by [Date] ASC,[Object Code] ASC,[From date] ASC,[Person_role] ASC,[Departure] ASC,[Room code] ASC,[period_7_14] ASC

У меня есть 100% уверенность, что все новые строки будут вставлены «в конце» индекса, и только с этими параметрами (PAD_INDEX = ON, FILLFACTOR = 100) я мог бы достичь 0,01%индекса фрагментации после вставки.Что-то опасное в этих настройках с такими предположениями?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...