Es handelt sich um einen dedizierten Server mit folgenden Spezifikationen:
AMD Ryzen 7 3800X
64 GB ECC-RAM @ 2666 MHz
2 x 1,2 TB Intel P3600 NVMe SSD (ZFS RAID 1)
Der VM, auf der Discourse läuft, wurden 8 CPU-Kerne und 32 GB RAM zugewiesen.
Ich glaube, ich habe das Problem mit der ersten Abfrage gefunden, oder zumindest eine Möglichkeit, den Abfrageplaner anzuweisen, die richtige Entscheidung zu treffen. Hier ist die Abfrage, die nicht innerhalb von 16+ Stunden abgeschlossen wurde (dies ist für das „First Quote“-Abzeichen):
SELECT ub.id
FROM user_badges ub
LEFT JOIN (
SELECT ids.user_id, q.post_id, p3.created_at granted_at
FROM
(
SELECT p1.user_id, MIN(q1.id) id
FROM quoted_posts q1
JOIN badge_posts p1 ON p1.id = q1.post_id
JOIN badge_posts p2 ON p2.id = q1.quoted_post_id
WHERE (TRUE OR ( p1.id IN (-1) ))
GROUP BY p1.user_id
) ids
JOIN quoted_posts q ON q.id = ids.id
JOIN badge_posts p3 ON q.post_id = p3.id
) q ON q.user_id = ub.user_id
AND (q.post_id = ub.post_id OR NOT TRUE)
WHERE ub.badge_id = 15 AND q.user_id IS NULL
Wenn ich an der richtigen Stelle eine einzelne ORDER BY-Zeile hinzufüge, wird diese Abfrage nun in wenigen Sekunden abgeschlossen:
SELECT ub.id
FROM user_badges ub
LEFT JOIN (
SELECT ids.user_id, q.post_id, p3.created_at granted_at
FROM
(
SELECT p1.user_id, MIN(q1.id) id
FROM quoted_posts q1
JOIN badge_posts p1 ON p1.id = q1.post_id
JOIN badge_posts p2 ON p2.id = q1.quoted_post_id
WHERE (TRUE OR ( p1.id IN (-1) ))
GROUP BY p1.user_id
) ids
JOIN quoted_posts q ON q.id = ids.id
JOIN badge_posts p3 ON q.post_id = p3.id
ORDER BY ids.user_id
) q ON q.user_id = ub.user_id
AND (q.post_id = ub.post_id OR NOT TRUE)
WHERE ub.badge_id = 15 AND q.user_id IS NULL
Ich hätte gedacht, dass es intelligent genug ist, diese Sortierung an der richtigen Stelle vorzunehmen, aber es scheint nicht so zu sein… Trotzdem scheint die Lösung in diesem Fall ziemlich einfach zu sein.
Ich habe mich noch nicht wirklich mit der anderen Abfrage bezüglich percent_rank beschäftigt.