MySQL ORDER BY Оптимизация для нескольких соединений - PullRequest
1 голос
/ 30 декабря 2011

Мне нужна помощь в оптимизации некоторых запросов для моей базы данных. Я понимаю использование индексов для помощи в объединениях и упорядочении по операторам, чтобы ускорить процесс, но мне было интересно, есть ли некоторые методы, позволяющие избежать использования файловой сортировки и временного использования при использовании команды EXPLAIN. Вот пример того, что я использую.

SELECT a.id, DATE_FORMAT(a.submitted_at, '%d-%b-%Y') as submitted_at, a.user_id,
            data1.*, 
            data2.name, data2.type,
            u.first_name, u.last_name               
            FROM applications AS a 
            LEFT JOIN users AS u ON u.id = a.user_id
            LEFT JOIN score_table AS data1 ON data1.applications_id = a.id
            LEFT JOIN sections AS data2 ON data2.id = data1.section_id
            WHERE category_id = [value] && submitted_at IS NOT NULL
            ORDER BY data2.type

Опять же, индексы правильно используются в моих запросах, как показано выше. Если я уберу предложение ORDER BY, то запрос выполняется быстро благодаря использованию правильных индексов. Я понимаю, что порядок соединений может повлиять на производительность запроса. Когда я тестирую использование ORDER BY в таблице users, поскольку это следующая таблица после «const», она будет использовать только «Using where, Using Filesort» на EXPLAIN. Если я перейду к любой из других таблиц, мы попадем в проблему «Использование временного».

Мой вопрос: как лучше всего оптимизировать подобные запросы, чтобы они выполнялись быстрее и в лучшем случае избегали использования файловой сортировки / временных файлов в EXPLAIN? Я открыт для любых возможностей :) Меня более или менее интересует теория о том, как заставить такие запросы работать лучше, чем этот точный запрос, поскольку мне приходится выполнять все больше и больше этих глубоких запросов ORDER BY в база данных, над которой я работаю.

- EDIT -

Вот объяснение запроса выше .....

id  select_type     table   type    possible_keys               key         key_len     ref                 rows    Extra
1   SIMPLE          a       ref     category_id,submitted_at    category_id     4           const               49      Using where; Using temporary; Using filesort
1   SIMPLE          u       eq_ref  PRIMARY                     PRIMARY     4           a.user_id           1   
1   SIMPLE          data1   ref     app id                      app id      4           a.id                7   
1   SIMPLE          data2   eq_ref  PRIMARY                     PRIMARY     4           data1.section_id    1   

1 Ответ

4 голосов
/ 30 декабря 2011

Пара вещей.

  1. Вы уверены, что вам нужно использовать «LEFT JOIN»?Глядя на запрос, похоже, что вы можете избежать «INNER JOIN», который уменьшит количество потенциальных строк.

  2. Вы не опубликовали свою схему, но я предполагаю, что пользователи.id, Applications.user_id, Score_table.applications_id, Applications.id, section.id и Score_table.section_id являются целыми?Если они не целые, я настоятельно призываю вас преобразовать их.И если бы не первичные ключи, убедитесь, что они проиндексированы.

  3. Я бы не стал выполнять форматирование данных на уровне mysql (например, DATE_FORMAT), так как это создаст некоторые накладные расходы во время запроса, скорееЯ хотел бы отформатировать данные на уровне приложения.

  4. ORDER BY заставляет MySQL создать временную таблицу для правильной сортировки, поэтому убедитесь, что вам абсолютно необходимы эти функции.Если это так, убедитесь, что section.type проиндексирован.

  5. Я хотел бы рассмотреть возможность использования другого соглашения об именовании псевдонимов.data1 и data2 настолько абстрактны, что трудно понять, на что они на самом деле ссылаются.Я бы посоветовал вам использовать сокращенную конструкцию таблицы, к которой вы добавляете псевдонимы, например;приложение становится приложением (вместо a), Score_table становится счетом (вместо data1) и т. д.

...