Индекс SQL Server стоится

Я считал, что один из компромиссов для добавления индексов таблицы в SQL Server является увеличенной стоимостью, вставлять/обновлять/запросы на удаление для пользы выполнению запросов Select.

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

Давайте возьмем, УДАЛЯЮТ как пример и предполагают, что у меня есть следующая схема (простите псевдо-SQL),

TABLE Foo
 col1 int
,col2 int
,col3 int
,col4 int
PRIMARY KEY (col1,col2)

INDEX IX_1
col3
INCLUDE 
col4

Теперь, если я делаю заявление

DELETE FROM Foo WHERE col1=12 AND col2 > 34

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

Однако в этой точке это также должно обновить IX_1 и запрос, что я дал его, не дает очевидного эффективного пути к механизму базы данных, чтобы найти, что строки обновляют. Это вынуждено сделать полное индексное сканирование в этой точке? Механизм читает строки из кластерного индекса сначала и генерирует более умное внутреннее, удаляют против индекса?

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

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

Они все равны в этом случае? Есть ли некоторый способ, которым я могу оценить влияние удаления одного или нескольких из этих индексов, не имея необходимость на самом деле пробовать его?

8
задан yellowstar 4 April 2010 в 20:22
поделиться

1 ответ

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

  • ваш запрос будет использовать кластеризованный индекс для поиска строк
  • строки содержат другое значение индекса (c3)
  • с использованием другое значение индекса (c3) и значения кластеризованного индекса (c1, c2), он может найти совпадающие записи в другом индексе.

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

Все это, однако, имеет свою цену. Для каждой совпадающей строки:

  • он должен прочитать строку, чтобы узнать значение для c3
  • , он должен найти запись для (c3, c1, c2) в некластеризованном индексе
  • , которую он должен удалить вход оттуда тоже.

Кроме того, хотя в вашем случае запрос диапазона может быть эффективным для кластеризованного индекса (линейный доступ после нахождения совпадения), обслуживание других индексов, скорее всего, приведет к произвольному доступу к ним для каждой совпадающей строки . Произвольный доступ имеет гораздо более высокую стоимость, чем просто перечисление конечных узлов B + дерева , начиная с заданного совпадения.
Учитывая вышеуказанный запрос, больше времени тратится на обслуживание некластеризованного индекса - сумма сильно зависит от количества записей, выбранных с помощью col1 = 12 AND col2> 34 {{1 }} предикат.

Я предполагаю, что стоимость концептуально такая же, как если бы у вас не было вторичного индекса, но, например, отдельная таблица, содержащая (c3, c1, c2) как единственные столбцы в кластеризованном ключе, и вы выполнили DELETE для каждой совпадающей строки, используя (c3, c1, c2). Очевидно, что обслуживание индексов является внутренним для SQL Server и выполняется быстрее, но концептуально я полагаю, что вышесказанное близко.

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

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

3
ответ дан 6 December 2019 в 00:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: