Когда таблица базы данных становится достаточно большой, чтобы индекс был полезен? - PullRequest
7 голосов
/ 22 июня 2009

Гипотетически, в базе данных SQL Server, если у меня есть таблица с двумя полями int (скажем, отношение «многие ко многим»), которая участвует в объединениях между двумя другими таблицами, при каком приблизительном размере таблица становится достаточно большой, где выигрыш в производительности индексов в двух полях int преодолевает накладные расходы, налагаемые указанными индексами?

Существуют ли различия в архитектуре между различными версиями SQL Server, которые могут существенно изменить этот ответ?

Ответы [ 9 ]

11 голосов
/ 22 июня 2009

Для запросов, включающих небольшие части строк таблицы, индексы всегда полезны, будь то 100 строк или 1,000,000.

См. Эту запись в моем блоге для примеров с планами и подробностями работы:

Такие запросы:

SELECT  *
FROM    table1 t1
JOIN    table2 t2
ON      t2.col = t1.col

наиболее вероятно будет использовать HASH JOIN. Будет создана хеш-таблица для таблицы меньшего размера, а строки из более крупной таблицы будут использованы для проверки хеш-таблицы.

Для этого индекс не нужен.

Однако этот запрос:

SELECT  *
FROM    table1 t1
JOIN    table2 t2
ON      t2.col = t1.col
WHERE   t1.othercol = @value

будет использовать NESTED LOOPS: строки из внешней таблицы (table1) будут искать с помощью индекса на table1.othercol, а строки из внутренней таблицы (table2) будут искать с помощью индекса на table2.col.

Если у вас нет индекса для col1, будет использоваться HASH JOIN, который требует сканирования всех строк из обеих таблиц и дополнительных ресурсов для создания хэш-таблицы.

Индексы также полезны для таких запросов:

SELECT  t2.col
FROM    table1 t1
JOIN    table2 t2
ON      t2.col = t1.col

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

И, конечно, если вам нужно отсортировать данные и иметь индексы как table1.col, так и table2.col, тогда выполните следующий запрос:

SELECT  *
FROM    table1 t1
JOIN    table2 t2
ON      t2.col = t1.col
ORDER BY
        t2.col

, вероятно, будет использовать метод MERGE JOIN, который будет очень быстрым, если оба входных набора строк отсортированы, а его вывод также отсортирован, что означает, что ORDER BY выйдет свободно.

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

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

Обратите внимание, что создание индекса может повлиять на производительность DML, но это другая история.

1 голос
/ 22 июня 2009

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

Во многих случаях при оптимизации вам необходимо прочитать документы вашей конкретной СУБД, чтобы узнать больше о том, как она использует индексы, и связать это с запросами приложения, которое вы оптимизируете. Тогда вы можете точно настроить использование индекса.

1 голос
/ 22 июня 2009

Очень полезная ссылка: «Ответы на переломный момент» http://www.sqlskills.com/BLOGS/KIMBERLY/post/The-Tipping-Point-Query-Answers.aspx

1 голос
/ 22 июня 2009

Независимо от размера, при поиске всегда есть выигрыш в производительности при поиске.

Что касается накладных расходов, возникает вопрос: какие накладные расходы вы имеете в виду и как вы соотносите их со значением поиска? В конце концов, это два отдельных значения.

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

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

Итак, суть: вам почти всегда лучше иметь индекс. Начните с этой позиции и подождите, пока переиндексация не станет узким местом. Тогда вы можете посмотреть на альтернативы.

1 голос
/ 22 июня 2009

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

1 голос
/ 22 июня 2009

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

1 голос
/ 22 июня 2009

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

Я все еще считаю, что у каждой таблицы должен быть первичный ключ, если он у вас есть, то у вас уже есть индекс

1 голос
/ 22 июня 2009

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

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

0 голосов
/ 22 июня 2009

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

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

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