Коррелированные подзапросы могут быть неэффективными.
Вы хотите использовать LEFT JOIN
вместе с условием, что какой-то обязательный (NOT NULL) столбец в правой таблице IS NULL
.
Попробуйте это :
SELECT
*
FROM sentences AS s
LEFT JOIN customer_sentences AS cs ON s.id = cs.sentence_id AND cs.bot_id = a AND cs.created_at >= '2019-12-30 13:25:58'
LEFT JOIN customer_sentences AS cs2 ON s.id = cs2.sentence_id AND cs.created_at >= '2020-01-13 13:17:58'
LEFT JOIN customer_sentences AS cs3 ON s.id = cs3.sentence_id AND cs.customer_id = 153375
JOIN sentence_translations AS st ON s.id = st.sentence_id AND st.language_id = 1
WHERE cs.id IS NULL
AND cs2.id IS NULL
AND cs3.id IS NULL
Я также заметил, что ваши индексы неэффективны. Их исправление должно иметь большее влияние, чем оптимизация запроса. Ваш первый подзапрос будет использовать составной индекс на ['bot_id', 'created_at', 'sentence_id']
. Второй подзапрос будет использовать только часть created_at
из ['created_at', 'bot_id']
. Ваш третий подзапрос будет использовать индекс ['customer_id']
. Ваш четвертый подзапрос, вероятно, не будет использовать какой-либо индекс. Может быть, это крошечная таблица или у вас есть индексы для этой таблицы, которые вы не включили в вопрос.
Если вы создаете составной индекс в customer_sentences
, состоящий из первого sentence_id
, за которым следует created_at
, он может использоваться всеми подзапросами (или объединениями) в этой таблице. Подзапрос, пропущенный created_at
, все равно сможет использовать первую часть этого нового индекса. Может быть лучше индексировать только столбец sentence_id
. Ваши существующие индексы, вероятно, должны быть удалены. Индексы увеличивают время записи в таблицу, поскольку при каждой записи также необходимо обновить все индексы. Они также увеличивают размер диска вашей таблицы и, возможно, потребление памяти.
Вероятно, вам также следует создать индекс в sentence_translations
для sentence_id
.