MySQL GroupWise Максимальные проблемы производительности на столе для миллиона строк
-
13-12-2019 - |
Вопрос
Я пытаюсь найти простой способ улучшить производительность для очень активных форумов, где существует огромное количество сообщений, и MySQL больше не может делать в памяти таблицы в памяти, и, похоже, не в полном объеме индексов. < / P >.
Этот простой запрос находит самое последнее сообщение в каждой теме для пользователя, чтобы определить, есть ли у них какие-либо ответы, поскольку (позже сравнение TOPIC_TIME)
SELECT p.*, MAX(post_time) as post_time FROM forum_posts AS p
WHERE p.poster_id = '1' AND p.post_status = '0'
GROUP BY p.topic_id
ORDER BY post_time DESC
LIMIT 50
.
Простой, плоский стол выглядит что-то вроде
post_id | poster_id | topic_id | post_status | post_time | post_text
.
Однако это производительность распадается, когда есть миллион постов, и сами пользователь имеют десятки тысяч постов. MySQL может больше не сортировать таблицу в памяти, либо есть слишком много строк, чтобы сканировать. Это может занять до 3 секунд в использовании реального мира, что неприемлемо ИМХО, потому что он пробивает ЦП в течение этого времени и замедления всех остальных.
Я могу сделать любую комбинацию индекса конечно, но MySQL, похоже, в основном нравится использовать комбинацию
poster_id + post_time
.
Так что он просто выбирает посты на 50 тысяч человек одного пользователя, а затем запускает группировку по TOPIC_ID и сортировке. Странно добавление topic_id в индексную смесь, похоже, не помогает производительности, хотя это может быть порядок полей индекса?
Я пытался написать эквивалентное соединение вместо этого, чтобы я мог использовать более одного индекса, но я столкнулся с проблемами с тем, что каждая сторона должна быть отфильтрована по post_status и плакат.
Я думал, что это будет быстрее, по крайней мере, для первых немногих страниц, если MySQL можно сделать, чтобы сначала сортировать данные через это индекс по Post_time, а затем начните выбирать отчетливый Topic_id для пользователя в убывании заказывать. Я предполагаю, что потребует подзапросе, и не уверена, что подзвездовый призыц 50K будет лучше, все еще нуждается в временной таблице.
Конечно, фундаментальное решение было бы увеличение дизайна основного ядра, чтобы существует еще одна таблица, которая просто хранит Max Post_time для каждого пользователя в каждой теме, но это слишком большое изменение, если ни один другой раствор не найден.
Спасибо за какие-либо предложения!
<Сильные> Добавление примера RealWorld и объясните:
<Сильный> медленный журнал
# Query_time: 2.751334 Lock_time: 0.000056 Rows_sent: 40 Rows_examined: 48286
SELECT p.*, MAX(post_time) as post_time FROM forum_posts AS p WHERE p.poster_id = '2' AND p.post_status = '0' GROUP BY p.topic_id ORDER BY post_time DESC LIMIT 7000, 40;
.
<Сильные> Объясните
select_type table type possible_keys key key_len ref rows Extra
SIMPLE p ref poster_time poster_time 4 const 27072 Using where; Using temporary; Using filesort
. Решение
Во-первых, исправьте ваш запрос, чтобы предоставить результаты определения:
SELECT p.topic_id,
MAX(post_time) as post_time
FROM forum_posts AS p
WHERE p.poster_id = '1' AND p.post_status = '0'
GROUP BY p.topic_id
ORDER BY post_time DESC
LIMIT 50 ;
.
Затем попробуйте добавить индекс на (post_status, poster_id, topic_id, post_time)
.