Улучшить производительность MySQL Select - PullRequest
0 голосов
/ 07 мая 2018

У меня есть выбор, чтобы получать товары от продавцов, за которыми следует заказчик. Этот продукт имеет лайки, комментарии, нужно считать лайки, нужно считать комментарии и показывать другие вещи. У меня есть where user in, чтобы получить клиентов, за которыми следует пользователь.

Проблема в том, что этот выбор занимает некоторое время, и я хотел бы знать, могу ли я как-то его улучшить. Все мои идентификаторы являются ключами.

select c.nome, p.foto, c.user, p.user, p.id, p.data, p.titulo, p.youtube, pp.foto, count(DISTINCT likes.user) as likes_count, count(distinct comentarios.id) as comentarios_count, count(DISTINCT l2.user) as count2 

from products p 

join users c on p.user=c.id 
left join profile_picture pp on p.user = pp.user
left join likes on likes.post = p.id
left join comentarios on comentarios.foto = p.id and comentarios.delete = 0  
left join likes l2 on l2.post = p.id and l2.user = ?

where (p.user in (select following from following where user =? and block=0) or p.user=?) and p.delete='0'
group by p.id
order by p.id desc limit ?

объяснить: enter image description here

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

Применить индекс в продуктах таблица с удалением и пользовательским столбцом (используйте составной индекс).

Применить соответствующий индекс ind users table

SELECT c.nome, p.foto, c.user, p.user, p.id, p.data, p.titulo, p.youtube, pp.foto, COUNT(DISTINCT likes.user) AS likes_count, COUNT(DISTINCT comentarios.id) AS comentarios_count, COUNT(DISTINCT l2.user) AS count2 

FROM products p 

LEFT JOIN users c ON p.user=c.id 
LEFT JOIN profile_picture pp ON p.user = pp.user
LEFT JOIN likes ON likes.post = p.id
LEFT JOIN comentarios ON comentarios.foto = p.id AND comentarios.delete = 0  
LEFT JOIN likes l2 ON l2.post = p.id AND l2.user = ?

WHERE c.id IS NOT NULL AND  (p.user IN (SELECT following FROM following WHERE USER =? AND block=0) OR p.user=?) AND p.delete='0'
GROUP BY p.id
ORDER BY p.id DESC LIMIT ?

Использование приведенного выше запроса может повысить производительность

0 голосов
/ 07 мая 2018

В дополнение к отличным рекомендациям Рэя для индексов я бы также предложил попробовать переписать IN в EXISTS. Оптимизаторы редко, чтобы никогда не могли сделать это сами, но обычно это дешевле. Так

p.user in (select following from following where user =? and block=0)

следует читать

exists (select * from following where user = ? and block = 0 and following = p.user)

.

Создайте составной индекс для following (user, following, block) или following (following, user, block) для поддержки подзапроса для указанного выше EXISTS. Здесь трудно догадаться, какие из user и following обладают лучшей селективностью. Они, вероятно, очень похожи, так что оба заказа должны делать. Чтобы быть уверенным, проверьте, какой столбец имеет более четкие значения в таблице, и укажите это первым.

0 голосов
/ 07 мая 2018

TL; DR

Из вашего объяснения выглядит, что у вас нет индексного ключа products на (user, delete, id). это, вероятно, самый большой удар для текущего запроса.

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

Короче говоря, если у вас нет серьезных проблем с памятью и памятью, и вы можете добавлять индексы в свои таблицы, я бы посоветовал вам иметь следующие индексы в ваших таблицах:

  • Составной индекс для таблицы products на (user, delete, id)
  • Составной индекс для таблицы likes на (post, user)
  • Составной индекс для таблицы comentarios по (foto, delete). Я НЕНАВИЖУ КОЛОННЫ ИМЕНИ ЗАБРОНИРОВАННЫХ СЛОВ (вроде УДАЛИТЬ) !!!!
  • Составной индекс для таблицы following на (user, block)

Это сделает объединения эффективными, но не на 100% покрывает, что, скорее всего, нежелательно в данном случае из выбранных вами значений.

Возможно, уже существуют существующие индексы, которые соответствуют приведенному выше, любые, которые начинаются с указанных выше значений (в точном порядке) в таблице, для которой он отмечен, будут достаточно хорошими. Например, если у вас есть индекс для таблицы likes на (post, user, some_other_column), он уже предоставит все необходимое для моего предложения индекса на (post, user). Ключом является то, что значения, необходимые из него, должны быть точно такими же.

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

Просто выбросив несколько дополнительных вещей:

  • Вы должны называть внешние ключи после таблицы и столбца, к которым они относятся. Например, comentarios.foto будет лучше называться comentarios.products_id, если это действительно идентификатор из таблицы продуктов. Такое четкое именование поможет предотвратить ошибки / ошибки, повысить эффективность написания новых запросов и минимизировать потерю здравого смысла для будущих разработчиков, пытающихся взломать вашу схему.
  • Как уже упоминалось несколькими комментаторами, узнайте, как читать Mysql EXPLAIN по вашим запросам. Просто буквально добавьте ключевое слово EXPLAIN перед запросом и запустите его. В результате вы узнаете, что механизм запросов изначально планирует сделать для выполнения вашего запроса (может на самом деле отклоняться во время выполнения, но, как правило, это очень удобно). Отсюда видно, где может потребоваться индекс для улучшения выполнения.
...