2012-01-18 2 views
5

Предположим, у вас есть запрос, как это ...Как сообщить оптимизатору MySQL использовать индекс в производной таблице?

SELECT T.TaskID, T.TaskName, TAU.AssignedUsers 
FROM `tasks` T 
    LEFT OUTER JOIN (
     SELECT TaskID, GROUP_CONCAT(U.FirstName, ' ', 
      U.LastName SEPARATOR ', ') AS AssignedUsers 
     FROM `tasks_assigned_users` TAU 
      INNER JOIN `users` U ON (TAU.UserID=U.UserID) 
     GROUP BY TaskID 
    ) TAU ON (T.TaskID=TAU.TaskID) 

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

Теперь ... Предположим, у вас есть настройки соответствующие индексы на tasks, users и tasks_assigned_users. Оптимизатор MySQL по-прежнему не будет использовать индекс TaskID при присоединении tasks к производной таблице. WTF?!?!?

Итак, мой вопрос ... как вы можете сделать этот запрос с помощью индекса на tasks_assigned_users.TaskID? Временные таблицы хромые, поэтому, если это единственное решение ... MySQL Optimizer - это глупо.

Индексы используются:

  • задача
    • ПЕРВИЧНЫХ - TaskID
  • пользователей
    • ПЕРВИЧНОГО - Идентификатор_пользователь
  • tasks_assigned_users
    • PRIMARY - (TaskID, Идентификатор_пользователя)
    • Дополнительный индекс UNIQUE - (Идентификатор_пользователя, TaskID)

EDIT: Кроме того, this page говорит, что производные таблицы выполняются/материализовался перед тем присоединяется произойти , Почему бы не повторно использовать ключи для выполнения соединения?

EDIT 2: MySQL Optimizer не позволит вам ставить index hints на производные таблицы (предположительно, потому что нет индексов на производных таблиц)

EDIT 3: Вот действительно хороший блог об этом : http://venublog.com/2010/03/06/how-to-improve-subqueries-derived-tables-performance/ Обратите внимание, что решение # 2 - это решение, которое я ищу, но похоже, что MySQL в настоящее время не поддерживает это. :(

EDIT 4: Просто найти this: «По MySQL 5.6.3, оптимизатор более эффективно обрабатывает подзапросы в предложении FROM (то есть производные таблицы): ... Во время выполнения запроса, оптимизатор может добавить индекс к производной таблице, чтобы ускорить извлечение строк из него. «Кажется перспективным ...

+0

Можете ли вы также добавить индексы, которые используете? Я предполагаю, что у вас есть PK для задач и не уникальный индекс для tasks_assigned_users. – Luis

+0

@ Luis - отредактировал вопрос для вас :) – BMiner

+0

У вас есть идентификатор группы GROUP BY, который подразумевает, что несколько человек могут работать над заданной задачей, что также подразумевает некоторую агрегацию. Вы хотите, чтобы все люди, назначенные для заданной задачи, были указаны в одном столбце возврата, связанном с задачей? Или вы действительно хотите, чтобы все были назначены на задание, а эти задачи не назначены, пусть это пустое. Возможно, даже нажмите любые задачи UNASSIGNED в верхнюю (или нижнюю) список ... – DRapp

ответ

4

Там есть решение для этого в сервере MySQL 5.6 - релиз предварительного просмотра (на момент написания этой статьи) ,

http://dev.mysql.com/doc/refman/5.6/en/from-clause-subquery-optimization.html

Хотя, я не уверен, если MySQL Optimizer будет повторно использовать индексы, которые уже существуют, когда она «добавляет индексы к производной таблице»

Рассмотрим следующий запрос:

SELECT * FROM t1 JOIN (SELECT * FROM t2) AS output_t2 ON t1.f1 = производный_t2.f1;

В документации говорится: «Оптимизатор строит индекс над столбцом f1 из производного_t2, если это разрешит использование доступа ref для плана выполнения с наименьшей стоимостью».

ОК, это здорово, но оптимизатор повторно использует индексы от t2? Другими словами, что, если индекс существует для t2.f1? Повторно используется этот индекс или оптимизатор воссоздает этот индекс для производной таблицы? Кто знает?

EDIT: Лучшее решение, пока MySQL 5.6 не создаст временную таблицу, не создаст индекс в этой таблице, а затем запустит запрос SELECT в таблице temp.

+1

такая же глупая ситуация на MariaDB 10 (спустя годы): даже если группа in in производная ускоряет запрос (смешной выбор v1 из t группы по v1) из-за явной сортировки, лучшим результатом является создание всех производных таблиц до основной запрос и явно добавить необходимые индексы. оптимизатор sux – Tertium

1

Я боюсь, это not possible. Вам нужно создать временную таблицу или представление для использования индекса.

+0

Это сообщение с 2006 года. С тех пор никаких изменений не было? – BMiner

+0

Я так не думаю по двум причинам. 1) Это MySQL. 2) Есть другие сообщения об этой проблеме с 2010 года, например (http://planet.mysql.com/entry/?id=23769). Кстати, не могли бы вы использовать представление? – AndreKR

+0

Я не знаю ... Я читал, что взгляды имеют схожие проблемы, но я дам ему попробовать прямо сейчас ... – BMiner

2

Проблема, которую я вижу, заключается в том, что при выполнении подзапроса отсутствует базовая индексированная таблица. Если у Вас есть производительность я бы сделать группировку в конце концов, что-то вроде этого:

SELECT T.TaskID, T.TaskName, GROUP_CONCAT(U.FirstName, ' ', U.LastName SEPARATOR ', ') AS AssignedUsers 
FROM `tasks` T 
    LEFT OUTER JOIN `tasks_assigned_users` TAU ON (T.TaskID=TAU.TaskID) 
    INNER JOIN `users` U ON (TAU.UserID=U.UserID) 
GROUP BY T.TaskID, T.TaskName 
+0

Это работает ... но поскольку это тот же самый набор результатов, я не знаю, почему MySQL не может сделать эту оптимизацию для меня. Кроме того, мой * актуальный * запрос имеет около 20 столбцов; Я должен сказать MySQL, чтобы сгруппировать их всех? Я * действительно * хочу группировать TaskID, а не TaskID и TaskName ... MySQL делает дополнительную работу, когда вы группируете оба столбца. Я знаю, что я имею в виду? – BMiner

+0

Попробуйте сказать и не говорить; если они необходимы, это ошибка, чтобы не объявлять их, поэтому вы легко поймете (я не знаю, нужны ли они).Я не знаю, почему он не может сделать оптимизацию; я предполагаю, что подзапросы - это черный ящик для внешнего запроса, но я не знаю. Обычно я избегаю подзапросов из-за проблем с производительностью, подобных этому. – Luis

+0

Является ли MySQL достаточно умным, чтобы знать, что GROUP BY T.TaskID, T.TaskName совпадает с GROUP BY T.TaskID, потому что T.TaskID является ключом PRIMARY? – BMiner

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

  • Нет связанных вопросов^_^