Я работаю над социальной сетью, где, как обычно, есть фид для пользователей, где они могут видеть действия пользователей, которых следуют пользователи, а не пользователи, которые заблокированы пользователями.
Это запрос, который в настоящее время используется в таблице "Действия"
SELECT DISTINCT 'activities'.'post_id'
FROM 'activities'
WHERE (activities.user_id IN ([followed_user_ids]) AND
activities.language_id IN ([language_ids]) AND
activities.id <= ?) AND
('activities'.'post_user_id' NOT IN ([blocked_and_deactivated_user_ids]))
ORDER BY 'activities'.'id' DESC
LIMIT 1 OFFSET 10
Это запрос, вызывающий проблемы. Иногда использование процессора Mysql достигает 100%, что вызывает проблемы у пользователей. Я также использовал индекс для столбцов, используемых в таблице действий.
В таблице "Деятельность" есть 10 миллионов записей.
Какие изменения я могу сделать, чтобы оптимизировать это?
Прежде всего, для производственной БД на RDS я бы предложил создать Read Read и перевести все эти тяжелые запросы SELECT в реплику. Здесь ссылка на документы. При этом вы уменьшите проблему с замораживанием для своих пользователей, так как тяжелые запросы не будут выполняться в том же экземпляре, что и обычная рабочая нагрузка.
Во-вторых, рассмотрите возможность создания индексов для таблиц, участвующих в этих тяжелых запросах. Чтобы правильно выбирать, какие индексы создавать, используйте оператор EXPLAIN и проверьте основные узкие места, то есть где запрос выполняет больше шагов для получения правильных данных.
Если вы действительно не можете избавиться от этих операторов IN (я думаю, что по крайней мере некоторые из них вы должны иметь возможность, например, следующие идентификаторы пользователей и языки, возможно, вы можете заменить IN простым соединением с использованием идентификатора пользователя) создавать индексы для задействованных колонны.
Дайте нам знать, как это происходит.
DISTINCT
здесь?