مهام Sidekiq طويلة الأمد

ومع ذلك، يجب تنفيذ الاستعلام الفرعي لحساب الرتب لكل موضوع في جدول المنشورات بالكامل، بغض النظر عن عدد الرتب التي يتم تحديثها فعليًا.

يستغرق هذا الاستعلام الفرعي حوالي 40 ثانية للتنفيذ، ثم يتم تضمينه داخل حلقة متداخلة يجب تشغيلها للدمج قبل حتى الوصول إلى جملة WHERE. يبدو أن هذا هو السبب في ارتفاع تكلفة الاستعلام بشكل كبير.

SELECT id, percent_rank()                                                     
    OVER (PARTITION BY topic_id ORDER BY SCORE DESC) as percent_rank 
FROM posts
إعجاب واحد (1)

لقد نظرت إلى الكود والآن فهمت. يتم تنفيذ هذا الاستعلام بشكل متكرر حتى يتم مسح جميع المنشورات التي تحتاج إلى تحديث رتبتها، لذا عندما كنت أراقب عمليات SQL، كنت أرى العديد من عمليات التشغيل المختلفة لهذا الاستعلام على مدار الساعات حيث ينتهي تشغيل واحد ويبدأ آخر.

ومع ذلك، لا يبدو أن LIMIT يساعد حقًا في تعقيد الاستعلام إلى حد كبير. في الواقع، اكتشفت أنه إذا زدت الحد إلى 200000، فإن خطة الاستعلام تتحسن بشكل ملحوظ.
مع 20000، أرى حلقة متداخلة ضخمة بتكلفة تقارب 200 مليون:

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

إذا قمت فقط بزيادة الحد إلى 200000، فإنه ينتج خطة الاستعلام هذه، التي تبدو أنظف بكثير:

                                                            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)

أتساءل ما الذي يسبب هذا التبديل. قد يكون من الجدير زيادة هذا الحد على الأقل بعد استيراد كبير مثل ما قمنا به بينما يتم تفريغ قائمة الانتظار.

إعجابَين (2)