Skip to content

Commit

Permalink
Had some fun looking to cut time spen ton aggregation. Cut a db call …
Browse files Browse the repository at this point in the history
…form aggregation, and add some indexes to cut time spent on aggregation a little more. Didn't do much, but didn't do much harm either. Cut the time by 5% or so. I think the main thing that might make it super fast now is to make it easy to aggregate several spaces, especially when doing something that affects a lot of spaces (e.g. adding a facility)
  • Loading branch information
DanielJackson-Oslo committed Mar 2, 2024
1 parent a013036 commit edc4c44
Show file tree
Hide file tree
Showing 10 changed files with 31 additions and 12 deletions.
1 change: 1 addition & 0 deletions app/models/facility_review.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def experience_icon
#
# index_facility_reviews_on_facility_id (facility_id)
# index_facility_reviews_on_space_id (space_id)
# index_facility_reviews_on_space_id_and_facility_id (space_id,facility_id)
# index_facility_reviews_on_space_id_and_user_id_and_facility_id (space_id,user_id,facility_id) UNIQUE
# index_facility_reviews_on_user_id (user_id)
#
Expand Down
6 changes: 5 additions & 1 deletion app/models/space.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ class Space < ApplicationRecord # rubocop:disable Metrics/ClassLength
south_east_lat:,
south_east_lng:)
}

# This scope cuts the db calls when aggregating space_facilities
has_many :facility_reviews_ordered_by_newest_first, -> { order(created_at: :desc) },
class_name: "FacilityReview", dependent: :destroy, inverse_of: :space
scope :with_aggregation_data, lambda {
preload(
:space_facilities,
:facility_reviews,
:facility_reviews_ordered_by_newest_first,
space_types: [
:facilities
]
Expand Down
5 changes: 3 additions & 2 deletions app/models/space_types_facility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ class SpaceTypesFacility < ApplicationRecord
#
# Indexes
#
# index_space_types_facilities_on_facility_id (facility_id)
# index_space_types_facilities_on_space_type_id (space_type_id)
# index_space_types_facilities_on_facility_id (facility_id)
# index_space_types_facilities_on_space_type_id (space_type_id)
# index_space_types_facilities_on_space_type_id_and_facility_id (space_type_id,facility_id) UNIQUE
#
# Foreign Keys
#
Expand Down
1 change: 1 addition & 0 deletions app/services/spaces/aggregate_facility_reviews_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def initialize(space:, facilities: [])
@facilities = facilities.any? ? facilities : Facility.order(:created_at)
@space_facilities = @space.space_facilities
@space_types = @space.space_types
@facility_reviews = @space.facility_reviews_ordered_by_newest_first
group_recent_facility_reviews_by_facility(count: 5)

super()
Expand Down
7 changes: 3 additions & 4 deletions app/services/spaces/concerns/countable_reviews.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ def most_recent_facility_reviews_for(facility)
end

def group_recent_facility_reviews_by_facility(count: 5)
@grouped_facility_reviews = @space.facility_reviews
.order(created_at: :desc)
.group_by(&:facility_id)
.transform_values { |reviews| reviews.first(count) }
@grouped_facility_reviews = @facility_reviews
.group_by(&:facility_id)
.transform_values { |reviews| reviews.first(count) }
end

def facility_reviews_for(facility)
Expand Down
9 changes: 9 additions & 0 deletions db/migrate/20240302202011_add_indexes_for_aggregations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddIndexesForAggregations < ActiveRecord::Migration[7.1]
def change
# Add index for facility_reviews on space_id and facility_id
add_index :facility_reviews, %i[space_id facility_id]

# Add index for space types facilities on space_type_id and facility_id
add_index :space_types_facilities, [:space_type_id, :facility_id], unique: true
end
end
4 changes: 3 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions spec/fabricators/facility_review_fabricator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#
# index_facility_reviews_on_facility_id (facility_id)
# index_facility_reviews_on_space_id (space_id)
# index_facility_reviews_on_space_id_and_facility_id (space_id,facility_id)
# index_facility_reviews_on_space_id_and_user_id_and_facility_id (space_id,user_id,facility_id) UNIQUE
# index_facility_reviews_on_user_id (user_id)
#
Expand Down
5 changes: 3 additions & 2 deletions spec/fabricators/space_types_facility_fabricator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
#
# Indexes
#
# index_space_types_facilities_on_facility_id (facility_id)
# index_space_types_facilities_on_space_type_id (space_type_id)
# index_space_types_facilities_on_facility_id (facility_id)
# index_space_types_facilities_on_space_type_id (space_type_id)
# index_space_types_facilities_on_space_type_id_and_facility_id (space_type_id,facility_id) UNIQUE
#
# Foreign Keys
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,12 @@ def experience(experience, other_facility = nil)
end

it "is performant for a changing a single facility, even if there are a large amount of other facilities" do
Array.new(10) { Fabricate(:facility, space_types: [space_type]) }
Array.new(20) { Fabricate(:facility, space_types: [space_type]) }
expect { space.aggregate_facility_reviews(facilities: [facility]) }.to perform_under(20).ms
end

it "is performant for a large amount of facilities" do
Array.new(10) { Fabricate(:facility, space_types: [space_type]) }
Array.new(20) { Fabricate(:facility, space_types: [space_type]) }
expect { space.aggregate_facility_reviews }.to perform_under(30).ms
end
end

0 comments on commit edc4c44

Please sign in to comment.