Стоимость индекса SQL Server - PullRequest
8 голосов
/ 05 апреля 2010

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

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

Давайте возьмем DELETE в качестве примера и предположим, что у меня есть следующая схема (простите за псевдо-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, которая перечисляет в разделе сведений другие индексы, которые необходимо обновить, но я не получаю никаких указаний на Относительная стоимость этих других показателей.

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

1 Ответ

3 голосов
/ 05 апреля 2010

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

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

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

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

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

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

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

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

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

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