Для этого запроса:
SELECT nf.id, nf.uuid, nf.leader_id, nf.data, nf.created_at, nfr.read_at
FROM notification_followers nf JOIN
user_follows uf
ON uf.leader_id = nf.leader_id AND uf.follower_id = 14 AND
uf.follow_status = 'follow' LEFT JOIN
notification_followers_read nfr
ON nf.id = nfr.notification_followers_id AND nfr.follower_id = 14
WHERE nf.created_at > uf.created_at
ORDER BY nf.id DESC
LIMIT 10;
Я бы порекомендовал индексы на user_follower(leader_id, follower_id, follow_status, created_at)
и notification_followers_read(notification_followers_id, follower_id, read_at)
.Порядок столбцов в индексах имеет значение.
Обратите внимание, что я изменил первое JOIN
на внутреннее соединение, потому что предложение WHERE
все равно превращает его в одно.
Хммм, давайте попробуем переписать запрос:
SELECT nf.id, nf.uuid, nf.leader_id, nf.data, nf.created_at,
(SELECT nfr.read_at
FROM notification_followers_read nfr
WHERE nf.id = nfr.notification_followers_id AND nfr.follower_id = 14
) nfr
FROM (SELECT nf.*
FROM notification_followers nf
WHERE EXISTS (SELECT 1
FROM user_follows uf
WHERE uf.leader_id = nf.leader_id AND uf.follower_id = 14 AND
uf.follow_status = 'follow' AND nf.created_at > uf.created_at
)
ORDER BY nf.id DESC
LIMIT 10
) nf;
Для этого вы должны быть уверены, что у вас есть индекс и на notification_followers(id)
.
В зависимости отваши данные, внутренний подзапрос может быть быстрее при таком подходе:
FROM (SELECT nf.*
FROM user_follows uf JOIN
notification_followers nf
ON uf.leader_id = nf.leader_id AND nf.created_at > uf.created_at
WHERE uf.follower_id = 14 AND uf.follow_status = 'follow'
ORDER BY nf.id DESC
LIMIT 10
) nf
Для этого индексы user_follows(follower_id, follow_status, leader_id, created_at)
и notification_followers(leader_id, created_at, id)
.Это может быть быстрее.