Skip to content

Chores/analyse performance problems

Kaspar Vollenweider requested to merge chores/analyse-performance-problems into develop

Anzeige Gruppenangebote

Slow query triggered at:

app/controllers/group_offers_controller.rb#L149

uses scope sorted_by_active_volunteer_count @ app/models/group_offer.rb#L86-98

[1] pry(#<GroupOffersController>)> @group_offers.explain
  GroupOffer Load (11.1ms)  SELECT group_offers.*, count(
              CASE WHEN group_assignments.termination_verified_by_id IS NULL AND
              active_storage_attachments.id IS NOT NULL AND
              group_assignments.period_start IS NOT NULL THEN 1 ELSE NULL END
            ) as active_volunteer_count_sort FROM "group_offers" LEFT OUTER JOIN "group_assignments" ON "group_assignments"."deleted_at" IS NULL AND "group_assignments"."group_offer_id" = "group_offers"."id" LEFT OUTER JOIN "active_storage_attachments" ON "active_storage_attachments"."record_type" = $1 AND "active_storage_attachments"."name" = $2 AND "active_storage_attachments"."record_id" = "group_assignments"."id" WHERE "group_offers"."deleted_at" IS NULL AND ("group_offers"."period_end" IS NULL OR "group_offers"."period_end" = NULL) GROUP BY "group_offers"."id" ORDER BY "group_offers"."active" DESC, "group_offers"."created_at" DESC  [["record_type", "GroupAssignment"], ["name", "pdf"]]
   (pry):7:in `init_sorts'
=> EXPLAIN for: SELECT group_offers.*, count(
              CASE WHEN group_assignments.termination_verified_by_id IS NULL AND
              active_storage_attachments.id IS NOT NULL AND
              group_assignments.period_start IS NOT NULL THEN 1 ELSE NULL END
            ) as active_volunteer_count_sort FROM "group_offers" LEFT OUTER JOIN "group_assignments" ON "group_assignments"."deleted_at" IS NULL AND "group_assignments"."group_offer_id" = "group_offers"."id" LEFT OUTER JOIN "active_storage_attachments" ON "active_storage_attachments"."record_type" = $1 AND "active_storage_attachments"."name" = $2 AND "active_storage_attachments"."record_id" = "group_assignments"."id" WHERE "group_offers"."deleted_at" IS NULL AND ("group_offers"."period_end" IS NULL OR "group_offers"."period_end" = NULL) GROUP BY "group_offers"."id" ORDER BY "group_offers"."active" DESC, "group_offers"."created_at" DESC [["record_type", "GroupAssignment"], ["name", "pdf"]]
                                                             QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=168.52..168.74 rows=87 width=481)
   Sort Key: group_offers.active DESC, group_offers.created_at DESC
   ->  HashAggregate  (cost=164.84..165.72 rows=87 width=481)
         Group Key: group_offers.id
         ->  Hash Left Join  (cost=50.70..162.14 rows=541 width=493)
               Hash Cond: (group_assignments.id = active_storage_attachments.record_id)
               ->  Hash Right Join  (cost=13.15..120.50 rows=541 width=493)
                     Hash Cond: (group_assignments.group_offer_id = group_offers.id)
                     ->  Seq Scan on group_assignments  (cost=0.00..103.93 rows=1280 width=28)
                           Filter: (deleted_at IS NULL)
                     ->  Hash  (cost=12.06..12.06 rows=87 width=473)
                           ->  Seq Scan on group_offers  (cost=0.00..12.06 rows=87 width=473)
                                 Filter: ((deleted_at IS NULL) AND (period_end IS NULL))
               ->  Hash  (cost=35.20..35.20 rows=188 width=16)
                     ->  Bitmap Heap Scan on active_storage_attachments  (cost=15.38..35.20 rows=188 width=16)
                           Recheck Cond: (((record_type)::text = 'GroupAssignment'::text) AND ((name)::text = 'pdf'::text))
                           ->  Bitmap Index Scan on index_active_storage_attachments_uniqueness  (cost=0.00..15.34 rows=188 width=0)
                                 Index Cond: (((record_type)::text = 'GroupAssignment'::text) AND ((name)::text = 'pdf'::text))
(18 rows)

A version without the attachment in the sort would be quite a bit faster:

    active_assignment_count_select = <<-SQL.squish
      group_offers.*, count(
        CASE WHEN
            group_assignments.termination_verified_by_id IS NULL
          AND
            group_assignments.period_start IS NOT NULL
          THEN 1
          ELSE NULL
        END
      ) as active_volunteer_count_sort
    SQL
    direction = :desc if direction.blank?
    left_joins(:group_assignments)
      .select(active_assignment_count_select)
      .group(:id)
      .order(active_volunteer_count_sort: direction)
[6] pry(#<GroupOffersController>)> @group_offers.explain
  GroupOffer Load (6.1ms)  SELECT group_offers.*, count( CASE WHEN group_assignments.termination_verified_by_id IS NULL AND group_assignments.period_start IS NOT NULL THEN 1 ELSE NULL END ) as active_volunteer_count_sort FROM "group_offers" LEFT OUTER JOIN "group_assignments" ON "group_assignments"."deleted_at" IS NULL AND "group_assignments"."group_offer_id" = "group_offers"."id" WHERE "group_offers"."deleted_at" IS NULL AND ("group_offers"."active" = TRUE AND ("group_offers"."period_end" IS NULL OR "group_offers"."period_end" = NULL)) GROUP BY "group_offers"."id" ORDER BY "group_offers"."active" DESC, "group_offers"."created_at" DESC
   (pry):14:in `init_sorts'
=> EXPLAIN for: SELECT group_offers.*, count( CASE WHEN group_assignments.termination_verified_by_id IS NULL AND group_assignments.period_start IS NOT NULL THEN 1 ELSE NULL END ) as active_volunteer_count_sort FROM "group_offers" LEFT OUTER JOIN "group_assignments" ON "group_assignments"."deleted_at" IS NULL AND "group_assignments"."group_offer_id" = "group_offers"."id" WHERE "group_offers"."deleted_at" IS NULL AND ("group_offers"."active" = TRUE AND ("group_offers"."period_end" IS NULL OR "group_offers"."period_end" = NULL)) GROUP BY "group_offers"."id" ORDER BY "group_offers"."active" DESC, "group_offers"."created_at" DESC
                                          QUERY PLAN
----------------------------------------------------------------------------------------------
 Sort  (cost=122.19..122.27 rows=35 width=481)
   Sort Key: group_offers.active DESC, group_offers.created_at DESC
   ->  HashAggregate  (cost=120.94..121.29 rows=35 width=481)
         Group Key: group_offers.id
         ->  Hash Right Join  (cost=12.50..119.85 rows=217 width=485)
               Hash Cond: (group_assignments.group_offer_id = group_offers.id)
               ->  Seq Scan on group_assignments  (cost=0.00..103.93 rows=1280 width=20)
                     Filter: (deleted_at IS NULL)
               ->  Hash  (cost=12.06..12.06 rows=35 width=473)
                     ->  Seq Scan on group_offers  (cost=0.00..12.06 rows=35 width=473)
                           Filter: ((deleted_at IS NULL) AND active AND (period_end IS NULL))
(11 rows)
Edited by Kaspar Vollenweider

Merge request reports