ここでの問題は、質問の更新2で説明したとおりでした。 MySQLはインデックスを使用して、ORDERBY操作をすばやく実行します。具体的には、MySQLはB-trees を使用します。 列(タイムスタンプ-p.time / r.timeなど)にインデックスを付けるには、少し多くのスペースを使用しますが、より高速な並べ替えが可能になります。
私のクエリの問題は、2つのテーブルの時間列で並べ替えられていて、可能な場合は再投稿テーブルのタイムスタンプを使用し、それ以外の場合は投稿テーブルを使用していたことです。 MySQLは両方のテーブルのBツリーを組み合わせることができないため、2つの異なるテーブルの列に対して高速なインデックスの並べ替えを実行できません。
これを解決するために、クエリとテーブル構造を2つの方法で変更しました。
1)最初にブロックされたユーザーに基づいてフィルタリングを実行するため、現在のユーザーがアクセスできる投稿に対してのみ注文を行う必要があります。これは問題の根本ではありませんでしたが、実用的な最適化です。例:
SELECT * FROM (SELECT * FROM Post p WHERE p.author_id NOT IN (4, 5, 6...))...
2)すべての投稿を作成者による再投稿として扱うため、すべての投稿には、インデックス付けと並べ替えを行うための結合可能な再投稿とrepost.timeが保証されます。例:
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
1日の終わりに、問題はORDER BYに帰着しました。このアプローチにより、クエリ時間が約8秒から20ミリ秒に短縮されました。