Оптимизация SQL-запросов - PullRequest
1 голос
/ 24 января 2012

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

По сути, я пытаюсь ускорить это приложение django (примечание: я не проектировал это ... просто застрял в его поддержке), и самая большая проблема заключается в том, что эти запросы генерируются администратором. У нас есть класс контента, от которого наследуются 4-5 других подклассов, и каждый раз, когда главный администратор запрашивает главный список, генерируется такой запрос:

SELECT `content_content`.`id`,
       `content_content`.`issue_id`,
       `content_content`.`slug`,
       `content_content`.`section_id`,
       `content_content`.`priority`,
       `content_content`.`group_id`,
       `content_content`.`rotatable`,
       `content_content`.`pub_status`,
       `content_content`.`created_on`,
       `content_content`.`modified_on`,
       `content_content`.`old_pk`,
       `content_content`.`content_type_id`,
       `content_image`.`content_ptr_id`,
       `content_image`.`caption`,
       `content_image`.`kicker`,
       `content_image`.`pic`,
       `content_image`.`crop_x`,
       `content_image`.`crop_y`,
       `content_image`.`crop_side`,
       `content_issue`.`id`,
       `content_issue`.`special_issue_name`,
       `content_issue`.`web_publish_date`,
       `content_issue`.`issue_date`,
       `content_issue`.`fm_name`,
       `content_issue`.`arts_name`,
       `content_issue`.`comments`,
       `content_section`.`id`,
       `content_section`.`name`,
       `content_section`.`audiodizer_id`
  FROM `content_image`
 INNER
  JOIN `content_content`
    ON `content_image`.`content_ptr_id` = `content_content`.`id`
 INNER
  JOIN `content_issue`
    ON `content_content`.`issue_id` = `content_issue`.`id`
 INNER
  JOIN `content_section`
    ON `content_content`.`section_id` = `content_section`.`id`
 WHERE NOT ( `content_content`.`pub_status` = -1 )
 ORDER BY `content_issue`.`issue_date` DESC LIMIT 30

Я запустил ОБЪЯСНЕНИЕ на это и получил следующее:

+----+-------------+-----------------+--------+-------------------------------------------------------------------------------------------------+---------+---------+--------------------------------------+-------+---------------------------------+
| id | select_type | table           | type   | possible_keys                                                                                   | key     | key_len | ref                                  | rows  | Extra                           |
+----+-------------+-----------------+--------+-------------------------------------------------------------------------------------------------+---------+---------+--------------------------------------+-------+---------------------------------+
|  1 | SIMPLE      | content_image   | ALL    | PRIMARY                                                                                         | NULL    | NULL    | NULL                                 | 40499 | Using temporary; Using filesort |
|  1 | SIMPLE      | content_content | eq_ref | PRIMARY,issue_id,content_content_issue_id,content_content_section_id,content_content_pub_status | PRIMARY | 4       | content_image.content_ptr_id         |     1 | Using where                     |
|  1 | SIMPLE      | content_section | eq_ref | PRIMARY                                                                                         | PRIMARY | 4       | content_content.section_id           |     1 |                                 |
|  1 | SIMPLE      | content_issue   | eq_ref | PRIMARY                                                                                         | PRIMARY | 4       | content_content.issue_id             |     1 |                                 |
+----+-------------+-----------------+--------+-------------------------------------------------------------------------------------------------+---------+---------+--------------------------------------+-------+---------------------------------+

Теперь из того, что я прочитал, мне нужно как-то выяснить, как сделать запрос к content_image не ужасным; Тем не менее, я рисую пробел, с чего начать. SQL не совсем моя сильная сторона, поэтому любая помощь будет высоко ценится.

1 Ответ

2 голосов
/ 24 января 2012

В настоящее время, судя по плану выполнения, MySQL начинает с content_image, получая все строки и только после этого используя первичные ключи для других таблиц: content_image имеет внешний ключ для content_content и content_content имеет внешние ключи для content_issue и content_section. Кроме того, только после того, как все объединения завершены, он может широко использовать ORDER BY content_issue.issue_date DESC LIMIT 30, поскольку он не может определить, какое из этих объединений может завершиться неудачей, и, следовательно, сколько записей из content_issue действительно потребуется, прежде чем он сможет получить первые тридцать строк вывода.

Итак, я бы попробовал следующее:

  • Измените JOIN content_issue на JOIN (SELECT * FROM content_issue ORDER BY issue_date DESC LIMIT 30) content_issue. Это позволит MySQL, если он начинается с content_issue и работает с другими таблицами, получить очень маленькое подмножество content_issue.
    • Примечание: собственно говоря, это меняет семантику запроса: это означает, что будут извлечены только записи не более чем за последние 30 content_issue с, и, следовательно, если некоторые из этих проблем не имеют опубликованного контента с изображения, то будет извлечено менее 30 записей. У меня недостаточно информации о ваших данных, чтобы оценить, действительно ли это изменение семантики изменит ваши результаты.
    • Также обратите внимание: я не предлагаю удалять ORDER BY content_issue.issue_date DESC LIMIT 30 в конце запроса. Я думаю, что вы хотите это в обоих местах.
  • Добавьте индекс на content_issue.issue_date, чтобы оптимизировать вышеуказанный подзапрос.
  • Добавьте индекс для content_image.content_ptr_id, чтобы MySQL мог работать с content_content до content_image без полного сканирования таблицы.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...