From c85d00fcb8f88fcd5fadf652e854fe9a08740124 Mon Sep 17 00:00:00 2001 From: Pau Perez Date: Mon, 29 Jul 2019 19:52:50 +0200 Subject: [PATCH] Remove N+1 while fetching distributors of OCs What used to be done as ```sql SELECT "order_cycles".* FROM "order_cycles" WHERE (order_cycles.orders_open_at <= '2019-07-29 17:45:20.137294' AND order_cycles.orders_close_at >= '2019-07-29 17:45:20.137333') SELECT DISTINCT "enterprises".* FROM "enterprises" INNER JOIN "exchanges" ON "enterprises"."id" = "exchanges"."receiver_id" WHERE "exchanges"."order_cycle_id" = 1 AND "exchanges"."incoming" = 'f' (...) SELECT DISTINCT "enterprises".* FROM "enterprises" INNER JOIN "exchanges" ON "enterprises"."id" = "exchanges"."receiver_id" WHERE "exchanges"."order_cycle_id" = 4 AND "exchanges"."incoming" = 'f' ``` it became ```sql SELECT "order_cycles".* FROM "order_cycles" WHERE (order_cycles.orders_open_at <= '2019-07-29 17:45:20.137294' AND order_cycles.orders_close_at >= '2019-07-29 17:45:20.137333') SELECT "exchanges".* FROM "exchanges" WHERE "exchanges"."incoming" = 'f' AND "exchanges"."order_cycle_id" IN (1, 2, 3, 4) SELECT "enterprises".* FROM "enterprises" WHERE "enterprises"."id" IN (3, 4, 5, 6) ``` I haven't got any perf numbers yet but each of the N+1 queries took as long as the single `enterprises` query on my dev machine. This should have a noticeable perf impact since the changed method belongs to the `BaseController` seems to be executed in all HTML requests as it gets called by ```ruby before_filter :warn_invalid_order_cycles, if: :html_request? ``` --- app/controllers/spree/admin/base_controller_decorator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/spree/admin/base_controller_decorator.rb b/app/controllers/spree/admin/base_controller_decorator.rb index 941b679c59..7e5293024d 100644 --- a/app/controllers/spree/admin/base_controller_decorator.rb +++ b/app/controllers/spree/admin/base_controller_decorator.rb @@ -61,7 +61,7 @@ Spree::Admin::BaseController.class_eval do def active_distributors_not_ready_for_checkout ocs = OrderCycle.managed_by(spree_current_user).active - distributors = ocs.map(&:distributors).flatten.uniq + distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout end