7

Есть запрос, который выполняется 7 секунд. Записей в таблице img около 10к.

SELECT img.id,date,title,url,views,votes,values,name
  FROM img
  INNER JOIN img_views ON img.id = img_views.m
  INNER JOIN img_rating ON img.id = img_rating.m
  INNER JOIN users ON img.user = users.id
  WHERE status = '1'
  ORDER BY img.id DESC LIMIT 0, 10

Тестами выяснил, что тормоза идут от INNER JOIN img_views и INNER JOIN img_rating. В этих таблицах хранятся данные о рейтинге записей и количество просмотров, по 10к в каждой таблице.

Есть ли способ оптимизировать запрос? И есть ли смысл хранить данные о рейтинге записей и количество просмотров в других таблицах? Таблицы в InnoDB.

Mike
  • 44,087
Rufex
  • 839
  • 1
    Выполните explain для вашего запроса и приложите к вопросу. И немного подробнее обрисуйте структуру таблиц, особенно интересует наличие индексов на колонках, участвующих в ON. И status он в какой у вас таблице. Невозможно дать рекомендаций не понимая для чего вообще созданы views и rating например и какую они еще несут нагрузку кроме хранения неких колонок, которых в данном запросе даже не видно что откуда – Mike Feb 05 '16 at 18:51
  • 2
    Если views и rating содержат по 10к записей, т.е. столько же, сколько в основной таблице - означает ли это что у записей из них связь с img однин-к-одному, если так, то эти таблицы скорее всего не нужны, особенно если кроме id хранят по одному полю – Mike Feb 05 '16 at 18:55
  • @Mike таблицу с рейтингом можно перенести в основную, она редко упдатится, но как быть с просмотрами, при каждом просмотре записи set VIEWS=VIEWS+1, то есть блок таблицы, не скажется ли он на производительности? – Rufex Feb 05 '16 at 19:12
  • не скажется. Выносить в другую таблицу надо когда связь один ко многим, например если вы бы хранили кто именно просматривал. И то в таких случаях общее кол-во для быстроты чтения в основную таблицу выносят. – Mike Feb 05 '16 at 19:15
  • @Mike и, как понимаю, в InnoDB блок построчно, так что смело можно всё в одну сливать? – Rufex Feb 05 '16 at 19:18
  • 1
    Не понял последнюю фразу. в блоке N записей, смотря сколько помещается. В поля типа view главное изначально класть 0, а не NULL, что бы место сразу резервировалось и потом при обновлении длина записи не росла. Все единичные значения стоит класть прямо в запись. Конечно запись в img длиннее и в блоке их меньше, но все равно при том же самом просмотре, который вы хотите посчитать этот блок поднимается с диска что бы скрипт взял из нее url, так что на момент update она уже будет в памяти и дополнительных обращений помимо собственно записи не потребует – Mike Feb 05 '16 at 20:51
  • без show create table для всех таблиц это бессмысленный разговор, на самом деле – strangeqargo Aug 06 '16 at 13:40

1 Answers1

1

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