MySql Query очень медленно - PullRequest
       11

MySql Query очень медленно

3 голосов
/ 09 августа 2011

Я выполняю следующий запрос в своей базе данных:

SELECT e.id_dernier_fichier
FROM Enfants e JOIN FichiersEnfants f
ON e.id_dernier_fichier = f.id_fichier_enfant

И запрос работает нормально. Если я модифицирую запрос следующим образом:

SELECT e.codega
FROM Enfants e JOIN FichiersEnfants f
ON e.id_dernier_fichier = f.id_fichier_enfant

Запрос становится очень медленным! Проблема в том, что я хочу выделить много столбцов в таблице e и f, и запрос может занять до 1 минуты! Я пробовал разные модификации, но ничего не работает. У меня есть индексы на id_ * также на e.codega. Enfants имеет 9000 строк, а FichiersEnfants - 20000 строк. Есть предложения?

Вот запрашиваемая информация (извините, что не показала их с самого начала):

Table FichiersEnfants Table Enfants Index Enfants Explain Query 1 Explain Query 2

1 Ответ

2 голосов
/ 09 августа 2011

Разница в производительности составляет возможно из-за того, что e.id_dernier_fichier находится в индексе, используемом для JOIN, но e.codega не находится в , что index .

Без полного определения обеих таблиц и всех их индексов невозможно сказать наверняка. Также может помочь включение двух ПЛАНОВ ОБЪЯСНЕНИЯ для двух запросов.


Однако сейчас я могу остановиться на нескольких вещах ...

Если ИНДЕКС КЛАСТЕРНЫЙ (это также относится к ПЕРВИЧНЫМ КЛЮЧАМ), данные фактически физически сохраняются в порядке ИНДЕКСА. Это означает, что зная, что вы хотите положение x в INDEX, также бездействие означает, что вы хотите положение x в таблице.

Однако, если INDEX не кластеризован, INDEX просто предоставляет вам поиск. Фактически говоря, позиция x в INDEX соответствует позиции y в таблице.

Важное значение здесь имеет доступ к полям, не указанным в INDEX. Это означает, что вы действительно должны пойти в ТАБЛИЦУ, чтобы получить данные. В случае КЛАСТЕРНОГО ИНДЕКСА, вы уже там, накладные расходы на поиск этого поля довольно низкие. Однако, если ИНДЕКС не кластеризован, вам эффективно нужно присоединить СТОЛ к ИНДЕКСУ, а затем найти интересующее вас поле.


Примечание; Наличие составного индекса на (id_dernier_fichier, codega) очень отличается от наличия одного индекса на (id_dernier_fichier) и отдельного индекса на (codega).


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

Вы упоминаете, что хотите получить доступ к многим полям. Поместить все эти поля в составной индекс, пожалуй, не лучшее решение. Вместо этого вы можете захотеть создать CLUSTERED INDEX для (id_dernier_fichier). Это будет означать, что после определения * id_dernier_fichier * вы уже в нужном месте, чтобы получить все остальные поля.


РЕДАКТИРОВАТЬ Примечание о индексах MySQL и CLUSTERED

13.2.10.1. Кластерные и вторичные индексы

Каждая таблица InnoDB имеет специальный индекс, называемый кластеризованным индексом, в котором хранятся данные для строк:

  • Если вы определяете ПЕРВИЧНЫЙ КЛЮЧ в своей таблице, InnoDB использует его в качестве кластеризованного индекса.
  • Если вы не определили PRIMARY KEY для своей таблицы, MySQL выберет первый индекс UNIQUE, который имеет только столбцы NOT NULL, в качестве первичного ключа, а InnoDB использует его в качестве кластеризованного индекса.
  • Если в таблице нет PRIMARY KEY или подходящего индекса UNIQUE, InnoDB внутренне создает скрытый кластеризованный индекс в синтетическом столбце, содержащем значения идентификатора строки. Строки упорядочены по идентификатору, который InnoDB присваивает строкам в такой таблице. Идентификатор строки представляет собой 6-байтовое поле, которое монотонно увеличивается при вставке новых строк. Таким образом, строки, упорядоченные по идентификатору строки, физически находятся в порядке вставки.
...