В какой момент наличие индекса становится эффективным

9

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

Кто-нибудь знает о том, где будет этот предел, или знает о ресурсе, который укажет мне правильное направление?

SeanVDH
источник
Какое соотношение чтения / записи для вашего приложения? Если вы действительно интенсивно пишете, то, возможно, это тот момент, когда вам нужно учитывать компромисс между записями, но если это обычное приложение, я бы добавил необходимый индекс в 99% случаев (таблицы обычно растут, они вряд ли вернуться в размер).
Мариан

Ответы:

12

Точный предел действительно сложно определить заранее.

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

Эффективный (некластеризованный) индекс

  • предлагает большую избирательность , например, возвращает только очень маленький процент (<1%, <2%) от общего числа строк. Если избирательность не задана - оптимизатор запросов SQL Server, скорее всего, будет игнорировать этот индекс

  • в идеале должен покрывать запрос, т.е. возвращать все столбцы, требуемые запросом. Если вы можете создать индекс, который имеет 1 или 2 столбца индекса и включает еще несколько (2-4) столбцов в качестве включенных столбцов, и, таким образом, вы можете покрыть запрос - тогда, скорее всего, оптимизатор запросов будет использовать этот индекс. Это также означает: если ваш код всегда использует SELECT * .....для извлечения всех столбцов , вероятность использования индексов снижается - довольно резко, на самом деле

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

PS: некластеризованные индексы на столбцах внешнего ключа являются особым случаем; по умолчанию я всегда рекомендовал бы добавлять их, поскольку они помогают ускорить как проверку ссылочной целостности, так и проверку JOINэтих ограничений FK. Но даже здесь абсолютно справедливо «расширять» эти индексы столбцов FK, добавляя некоторые дополнительные столбцы «include», чтобы сделать их еще более полезными.

marc_s
источник
2
Хотя этот ответ может и не дать прямого ответа на вопрос, он делает гораздо лучше, предоставляя важные принципы построения индекса, и отвечает на вопрос, который я должен был задать в первую очередь.
SeanVDH
6

Вы можете увидеть улучшение по сравнению с индексом только с 10 строками.

В следующем тесте на моей машине версия без индекса завершилась в 10.5секундах, а версия с индексом в 9.8секундах (в течение более 3 запусков).

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

CREATE TABLE T
(
X INT,
Y CHAR(100) NULL
)

INSERT INTO T (X)
SELECT number 
FROM master..spt_values
WHERE type='P' AND number BETWEEN 1 AND 10

set nocount on;

DECLARE @I INT, @X INT

DECLARE @Time DATETIME2(7) = SYSUTCDATETIME()

SET @I = 1
    WHILE (@I < 1000000)
    BEGIN
    SELECT @X = MAX(X)
    FROM T
    SET @I += 1
    END

SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())

CREATE CLUSTERED INDEX IX ON T(X)
SET @Time = SYSUTCDATETIME()
SET @I = 1
    WHILE (@I < 1000000)
    BEGIN
    SELECT @X = MAX(X)
    FROM T
    SET @I += 1
    END

SELECT DATEDIFF(MICROSECOND, @Time, SYSUTCDATETIME())

DROP TABLE T
Мартин Смит
источник
На вставки влияют одинаково, или замедление минимально?
SeanVDH
@SeanVDH - пример в моем ответе сравнивает кластерный индекс с кучей. Было бы понятно, что вставка между существующими строками будет медленнее, поскольку строки должны перемещаться в определенное место, а массив слотов перезаписывается, а также возможность разбиения страницы. Для больших вставок данные также могут быть отсортированы в порядке клавиш CI, что не нужно при вставке в кучу. Кимберли Трипп утверждает здесь , однако , что иногда вставляя в CI может быть лучше , чем вставить в кучу.
Мартин Смит
Спасибо за статью, она представляет некоторые интересные моменты. Мне было интересно, будут ли вставки затронуты так же сильно, как и выборки в маленькой таблице, но вы правы, компромисс должен быть примерно таким же в начале, как и позже.
SeanVDH