2013-08-01 2 views
4

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

так что если у меня есть следующие 2 таблицы

CREATE TABLE `accounts` (
`account_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
`name` varchar(60) NOT NULL, 
`owner_id` int(11) unsigned NOT NULL, 
PRIMARY KEY (`account_id`), 
KEY `owner_id` (`owner_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 


CREATE TABLE `users` (
`user_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
`name` varchar(60) NOT NULL 
PRIMARY KEY (`user_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

колонна account.owner_id связана с users.user_id, но без установки внешнего ключа.

, так что я могу сделать что-то вроде этого

SELECT 
a.name AS account_name, 
u.name AS user_name FROM 
accounts AS a INNER JOIN users AS u ON u.user_id = a.owner_id 

Таким образом, после изучения того, что внешние ключи и то, что они делают, я создал внешний ключ, как это.

Однако, я замечаю изменение производительности, поскольку система сильно замедляется. Я не уверен, добавит ли FOREIGN KEYs повторное использование производительности или нет? или есть ли снижение производительности при добавлении внешних ключей в таблицу? Обратите внимание, что в моей базе данных много таблиц и столбцов. поэтому я делаю много INNER/LEFT/RIGHT JOINS, и все столбцы, где я идентифицировал их как FOREIGN KEYS, индексируются. Заметки, что я не добавлял никаких индексов в эти столбцы, поскольку все они уже существуют до добавления ключей FOREIGN в мою базу данных.

мой вопрос, будут ли ИНОСТРАННЫЕ КЛЮЧИ снижать производительность на UPDATE/INSERT/DELETE/SELECT? Также есть преимущество добавления ограничения FOREIGN KEY, когда мы указали ON DELETE NO ACTION ON UPDATE NO ACTION?

Благодаря

+0

С самого начала все, что вы сделали, выглядит правильно, и не должно было быть удара производительности. Вы уверены, что замедление связано с запросом, который вы предоставили? Попробуйте запустить тот же запрос с помощью EXPLAIN перед ним, посмотрите, обеспечивает ли оптимизатор какое-либо понимание. –

+0

Я не уверен, что он чувствует, что весь сайт замедлился, а не мирный запрос. он поднял флаг, когда вижу, что система работает медленно. Поэтому я не был уверен, является ли это проблемой FOREIGN KEYS или нет. так вы предлагаете использовать FK или нет? – Jaylen

+0

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

ответ

6

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

Внешние ключи также создают общую блокировку родительской таблицы во время некоторых обновлений дочерней таблицы. Это может помешать параллельным обновлениям этой таблицы и заставить систему выглядеть медленнее. См. http://www.mysqlperformanceblog.com/2006/12/12/innodb-locking-and-foreign-keys/

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


Re ваш комментарий:

Да, любое обновление дочерних таблиц создает эксклюзивную блокировку на модифицированном строки в дочерней таблице. Вероятно, вы ожидали этого. Но это действие также создает общий замок по ссылочной строке в clients. Любое количество сеансов может самостоятельно создавать общие блокировки в одной строке (отсюда и имя общего доступа). Но эксклюзивный замок требует, чтобы не было никакого замка любого типа.Поэтому, если в строке часто встречаются общие блокировки, то прямые обновления этой строки в clients не могут получить требуемую исключительную блокировку.

Назначение этих общих блокировок в основном состоит в том, что строка в clients не удаляется или не изменяется, когда кто-то обновляет строку, которая зависит от нее. Другими словами, «не удаляйте моего родителя». Но в зависимости от частоты обновлений и продолжительности транзакций это может затруднить выполнение обновлений родительской строки.

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

+0

Спасибо за этот подробный ответ, поэтому, если у меня есть клиентская таблица, и у меня есть 10 других таблиц, связанных с ней с помощью FK. Каждый раз, когда обновление делается на одну из этих 10 таблиц, происходит блокировка таблицы клиентов? если используется одна из этих таблиц, большинство моих запросов, то наверняка постоянные блокировки, размещенные на таблице клиентов, будут заблокированы большую часть времени. пожалуйста, помогите мне понять это. благодаря – Jaylen

Смежные вопросы