Trabajos de Sidekiq de larga duración

Aun así, tiene que ejecutar la subconsulta para calcular los rangos en cada tema de toda la tabla de publicaciones, sin importar cuántos rangos se estén actualizando realmente.

Esta subconsulta tarda unos 40 segundos en ejecutarse y, además, está dentro de un bucle anidado que debe ejecutarse para la unión antes de llegar incluso a la cláusula WHERE. Eso parece ser lo que dispara el costo de la consulta.

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

He revisado el código y ahora lo entiendo. Esta consulta se ejecuta repetidamente hasta que se eliminan todas las publicaciones cuyo rango necesita actualizarse. Por eso, cuando estaba observando los procesos SQL, veía muchas ejecuciones diferentes de esta consulta a lo largo de varias horas, ya que terminaba una ejecución y comenzaba otra.

Sin embargo, parece que el LIMIT no ayuda realmente a reducir la complejidad de la consulta tanto como uno esperaría. De hecho, he descubierto que si aumento el límite a 200000, el plan de consulta mejora significativamente.
Con 20000, veo un bucle anidado enorme con un costo de casi 200 millones:

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

Si simplemente aumento el límite a 200000, entonces produce este plan de consulta, que se ve mucho más limpio:

                                                            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)

Me pregunto qué causa este cambio. Podría valer la pena aumentar este límite al menos después de una importación grande como la que hemos realizado, mientras se va limpiando el retraso acumulado.

2 Me gusta