Het probleem hier was zoals ik beschreef in update 2 van mijn vraag. MySQL gebruikt indexen om ORDER BY-bewerkingen snel uit te voeren. Meer specifiek gebruikt MySQL B-trees om kolommen te indexeren (zoals tijdstempels - p.time/r.time), die wat meer ruimte in beslag nemen maar sneller sorteren mogelijk maken.
Het probleem met mijn vraag was dat het sorteerde op de tijdkolom in twee tabellen, waarbij de tijdstempel uit de repost-tabel werd gebruikt, indien beschikbaar, en anders de post-tabel. Aangezien MySQL de B-trees van beide tabellen niet kan combineren, kan het geen snelle indexsortering uitvoeren op kolommen uit twee verschillende tabellen.
Ik heb mijn query- en tabelstructuur op twee manieren aangepast om dit op te lossen.
1) Voer eerst een filter uit op basis van geblokkeerde gebruikers, dus bestellen hoeft alleen te gebeuren op berichten die toegankelijk zijn voor de huidige gebruiker. Dit was niet de kern van het probleem, maar is praktische optimalisatie. bijv.
SELECT * FROM (SELECT * FROM Post p WHERE p.author_id NOT IN (4, 5, 6...))...
2) Behandel elke post als een repost door de auteur, dus elke post heeft gegarandeerd een herplaatsbare repost en repost.time waarop kan worden geïndexeerd en gesorteerd. bijv.
SELECT * FROM (...) LEFT JOIN p.reposts repost ON (p.id = repost.post_id AND
repost.time = (
SELECT MIN(r.time) FROM Repost r WHERE p.id = r.post_id
AND r.user_id IN (1, 2, 3...) AND r.user_id NOT IN (4, 5, 6...))
))
WHERE (repost.id IS NOT NULL) ORDER BY repost.time DESC LIMIT 0, 10
Aan het eind van de dag kwam het probleem neer op ORDER BY - deze aanpak verkortte de querytijd van ongeveer 8 seconden tot 20 ms.