Vấn đề ở đây như tôi đã mô tả trong bản cập nhật 2 của câu hỏi của tôi. MySQL sử dụng các chỉ mục để thực hiện các thao tác ORDER BY một cách nhanh chóng. Cụ thể hơn, MySQL sử dụng B-tree để lập chỉ mục các cột (chẳng hạn như dấu thời gian - p.time / r.time), sử dụng nhiều dung lượng hơn một chút nhưng cho phép sắp xếp nhanh hơn.
Vấn đề với truy vấn của tôi là nó đang sắp xếp theo cột thời gian trong hai bảng, sử dụng dấu thời gian từ bảng đăng lại nếu có và bảng đăng nếu không. Vì MySQL không thể kết hợp các cây B từ cả hai bảng nên nó không thể thực hiện sắp xếp chỉ mục nhanh trên các cột từ hai bảng khác nhau.
Tôi đã sửa đổi truy vấn và cấu trúc bảng của mình theo hai cách để giải quyết vấn đề này.
1) Thực hiện lọc dựa trên người dùng bị chặn trước, vì vậy việc đặt hàng chỉ phải được thực hiện trên các bài đăng mà người dùng hiện tại có thể truy cập. Đây không phải là gốc rễ của vấn đề, nhưng là tối ưu hóa thực tế. ví dụ:
SELECT * FROM (SELECT * FROM Post p WHERE p.author_id NOT IN (4, 5, 6...))...
2) Coi mọi bài đăng như một bài đăng lại của tác giả, vì vậy mỗi bài đăng được đảm bảo có thời gian đăng lại và đăng lại có thể kết hợp để lập chỉ mục và sắp xếp. ví dụ:
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
Vào cuối ngày, vấn đề đã đến với ORDER BY - cách tiếp cận này đã giảm thời gian truy vấn từ khoảng 8 giây xuống còn 20 mili giây.