Lavori Sidekiq di lunga durata

Tuttavia, deve comunque eseguire la subquery per calcolare le classifiche per ogni argomento in tutta la tabella dei post, indipendentemente da quanti ranking vengono effettivamente aggiornati.

Questa subquery richiede circa 40 secondi per essere eseguita ed è inserita all’interno di un ciclo nidificato che deve essere eseguito per la join prima ancora di arrivare alla clausola WHERE. Sembra che questo sia ciò che sta facendo esplodere il costo della query.

SELECT id, percent_rank()                                                     
    OVER (PARTITION BY topic_id ORDER BY SCORE DESC) as percent_rank 
FROM posts
1 Mi Piace

Ho esaminato il codice e ora ho capito. Questa query viene eseguita ripetutamente finché non vengono eliminati tutti i post il cui rango deve essere aggiornato; quindi, mentre osservavo i processi SQL, vedevo molte esecuzioni diverse di questa query nel corso delle ore, man mano che ne completava una e ne iniziava un’altra.

Tuttavia, non sembra che il LIMIT aiuti davvero a ridurre la complessità della query. Anzi, ho scoperto che se aumento il limite a 200000, il piano di esecuzione della query migliora significativamente.
Con 20000, vedo un enorme ciclo nidificato con un costo quasi di 200 milioni:

-> Nested Loop (cost=6033694.44..190270554.32 rows=26680560 width=16)

Se aumento semplicemente il limite a 200000, ottengo questo piano di esecuzione, che appare molto più pulito:

                                                            QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------
 Update on posts  (cost=7334394.89..8873863.82 rows=200000 width=833)
   ->  Nested Loop  (cost=7334394.89..8873863.82 rows=200000 width=833)
         ->  Subquery Scan on x  (cost=7334394.45..7370147.82 rows=200000 width=48)
               ->  Limit  (cost=7334394.45..7368147.82 rows=200000 width=12)
                     ->  Hash Join  (cost=7334394.45..11837188.36 rows=26680560 width=12)
                           Hash Cond: (posts_1.id = y.id)
                           Join Filter: ((posts_1.percent_rank IS NULL) OR (y.percent_rank <> posts_1.percent_rank))
                           ->  Hash Join  (cost=35403.20..2845221.73 rows=26703700 width=12)
                                 Hash Cond: (posts_1.topic_id = topics.id)
                                 ->  Seq Scan on posts posts_1  (cost=0.00..2739721.00 rows=26703700 width=16)
                                 ->  Hash  (cost=23918.11..23918.11 rows=918807 width=4)
                                       ->  Index Only Scan using topics_pkey on topics  (cost=0.42..23918.11 rows=918807 width=4)
                           ->  Hash  (cost=6834805.00..6834805.00 rows=26703700 width=12)
                                 ->  Subquery Scan on y  (cost=6033694.00..6834805.00 rows=26703700 width=12)
                                       ->  WindowAgg  (cost=6033694.00..6567768.00 rows=26703700 width=24)
                                             ->  Sort  (cost=6033694.00..6100453.25 rows=26703700 width=16)
                                                   Sort Key: posts_2.topic_id, posts_2.score DESC
                                                   ->  Seq Scan on posts posts_2  (cost=0.00..2739721.00 rows=26703700 width=16)
         ->  Index Scan using posts_pkey on posts  (cost=0.44..7.52 rows=1 width=789)
               Index Cond: (id = x.id)
 JIT:
   Functions: 30
   Options: Inlining true, Optimization true, Expressions true, Deforming true
(23 rows)

Mi chiedo cosa causi questo cambiamento. Potrebbe valere la pena aumentare questo limite almeno dopo un’importazione importante come quella che abbiamo fatto, mentre si svuota la coda di elaborazione.

2 Mi Piace