Улучшает ли внешний ключ производительность запросов? - PullRequest
138 голосов
/ 03 февраля 2009

Предположим, у меня есть 2 таблицы, продукты и категории продуктов. Обе таблицы имеют отношение к CategoryId. И это запрос.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

Когда я создаю план выполнения, таблица ProductCategories выполняет поиск по кластерному индексу, как и ожидалось. Но для таблиц Products он выполняет сканирование индекса кластера, что вызывает у меня сомнения. Почему FK не помогает улучшить производительность запросов?

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

Мои вопросы:

  1. Помимо ФК помогает ограничить отношения, есть ли у него какая-либо другая полезность? Улучшает ли это производительность запросов?

  2. Должен ли я создать индекс для всех столбцов FK (понравился Products.CategoryId) во всех таблицах?

Ответы [ 9 ]

173 голосов
/ 03 февраля 2009

Внешние ключи - это инструмент ссылочной целостности, а не инструмент производительности. По крайней мере в SQL Server создание FK не создает связанный индекс, и вы должны создавать индексы для всех полей FK, чтобы улучшить время поиска.

53 голосов
/ 03 февраля 2009

Иностранные ключи могут улучшить (и ухудшить) производительность

  1. Как указано здесь: Внешние ключи повышают производительность

  2. Вы должны всегда создавать индексы для столбцов FK, чтобы уменьшить количество поисков. SQL Server не делает этого автоматически.

Редактировать

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

Может ли внешний ключ улучшить производительность

Ограничение внешнего ключа повышает производительность во время чтения данные, но в то же время это замедляет производительность во время вставка / изменение / удаление данных.

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

13 голосов
/ 03 февраля 2009

Внешний ключ - это концепция СУБД для обеспечения целостности базы данных.

Любые последствия / улучшения производительности будут зависеть от используемой технологии базы данных и будут вторичными по отношению к назначению внешнего ключа.

Рекомендуется, чтобы в SQL Server все внешние ключи имели хотя бы некластеризованный индекс.

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

4 голосов
/ 03 февраля 2009

Ваша лучшая ставка на производительность - использовать индексы в полях, которые вы часто используете. Если вы используете SQL Server, вы можете использовать профилировщик для профилирования конкретной базы данных, взять файл, который выводится, и воспользоваться мастером настройки, чтобы получить рекомендации о том, где разместить ваши индексы. Мне также нравится использовать профилировщик для очистки долго выполняющихся хранимых процедур, у меня есть список из десяти худших правонарушителей, который я публикую каждую неделю, чтобы люди были честными: D.

3 голосов
/ 03 февраля 2009

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

Итак, это:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

Становится так:

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

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

1 голос
/ 19 июня 2018

Для MySQL 5.7 он определенно может ускорить запросы, включающие множественные объединения!

Я использовал 'объяснение', чтобы понять мой запрос, и обнаружил, что я соединяю 4-5 таблиц - где ключи вообще не использовались. Я ничего не сделал, кроме добавления внешнего ключа к этим таблицам, и в результате время загрузки сократилось на 90%. Запросы, которые заняли> 5 с, теперь занимают 500 мс или меньше.

Это ОГРОМНОЕ улучшение!

И, как уже упоминалось, вы получаете дополнительный бонус за обеспечение целостности отношений.

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

1 голос
/ 28 августа 2011

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

1 голос
/ 03 февраля 2009

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

0 голосов
/ 20 апреля 2017

Начиная с SQL Server 2008 внешние ключи могут влиять на производительность, влияя на то, как ядро ​​базы данных выбирает оптимизацию запроса. Обратитесь к разделу «Звездное объединение» в следующей статье: https://technet.microsoft.com/en-us/library/2008.04.dwperformance.aspx

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