muratguzel / letsrate

The best way to add rating capabilities to your rails application and your activerecord models.
http://letsrate.herokuapp.com
198 stars 234 forks source link

Rating average cached in model #80

Closed microweb10 closed 7 years ago

microweb10 commented 9 years ago

This will improve the performance when using rating_for helper.

Imagine that you want to show a list with many objects that are rateable, for each object letsrate had to make a query to the rating_cache database.

Simply adding an attribute to our rateable model we can easily store the average and reduce the queries, in consequence the performance will be improved.

Here there is a before/after example showing 5 objects

We can see that we passed from 11.8 ms to 3.3 ms (around 3 times faster)

10:27:58 web.1     | Started GET "/es/rutas/3" for 127.0.0.1 at 2015-03-01 10:27:58 +0100
10:27:58 web.1     | Processing by RoutesController#show as HTML
10:27:58 web.1     |   Parameters: {"locale"=>"es", "id"=>"3"}
10:27:58 web.1     |   Route Load (0.3ms)  SELECT  "routes".* FROM "routes"  WHERE "routes"."id" = $1 LIMIT 1  [["id", 3]]
10:27:58 web.1     |   Bar Load (0.5ms)  SELECT "bars".* FROM "bars"  WHERE "bars"."route_id" = $1  ORDER BY id DESC  [["route_id", 3]]
10:27:58 web.1     |   RatingCache Load (0.4ms)  SELECT  "rating_caches".* FROM "rating_caches"  WHERE "rating_caches"."cacheable_id" = $1 AND "rating_caches"."cacheable_type" = $2 AND "rating_caches"."dimension" = 'quality' LIMIT 1  [["cacheable_id", 15], ["cacheable_type", "Bar"]]
10:27:58 web.1     |   User Load (0.5ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
10:27:58 web.1     |    (0.4ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 15 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
10:27:58 web.1     |   RatingCache Load (0.2ms)  SELECT  "rating_caches".* FROM "rating_caches"  WHERE "rating_caches"."cacheable_id" = $1 AND "rating_caches"."cacheable_type" = $2 AND "rating_caches"."dimension" = 'quality' LIMIT 1  [["cacheable_id", 14], ["cacheable_type", "Bar"]]
10:27:58 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 14 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
10:27:58 web.1     |   RatingCache Load (0.4ms)  SELECT  "rating_caches".* FROM "rating_caches"  WHERE "rating_caches"."cacheable_id" = $1 AND "rating_caches"."cacheable_type" = $2 AND "rating_caches"."dimension" = 'quality' LIMIT 1  [["cacheable_id", 13], ["cacheable_type", "Bar"]]
10:27:58 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 13 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
10:27:58 web.1     |   RatingCache Load (0.3ms)  SELECT  "rating_caches".* FROM "rating_caches"  WHERE "rating_caches"."cacheable_id" = $1 AND "rating_caches"."cacheable_type" = $2 AND "rating_caches"."dimension" = 'quality' LIMIT 1  [["cacheable_id", 12], ["cacheable_type", "Bar"]]
10:27:58 web.1     |    (0.3ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 12 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
10:27:58 web.1     |   RatingCache Load (0.3ms)  SELECT  "rating_caches".* FROM "rating_caches"  WHERE "rating_caches"."cacheable_id" = $1 AND "rating_caches"."cacheable_type" = $2 AND "rating_caches"."dimension" = 'quality' LIMIT 1  [["cacheable_id", 11], ["cacheable_type", "Bar"]]
10:27:58 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 11 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
10:27:58 web.1     |   Rendered routes/show.html.erb within layouts/application (48.0ms)
10:27:58 web.1     | Completed 200 OK in 169ms (Views: 124.4ms | ActiveRecord: 11.9ms)

11:38:51 web.1     | Started GET "/es/rutas/3" for 127.0.0.1 at 2015-03-01 11:38:51 +0100
11:38:51 web.1     | Processing by RoutesController#show as HTML
11:38:51 web.1     |   Parameters: {"locale"=>"es", "id"=>"3"}
11:38:51 web.1     |   Route Load (0.3ms)  SELECT  "routes".* FROM "routes"  WHERE "routes"."id" = $1 LIMIT 1  [["id", 3]]
11:38:51 web.1     |   Bar Load (0.3ms)  SELECT "bars".* FROM "bars"  WHERE "bars"."route_id" = $1  ORDER BY id DESC  [["route_id", 3]]
11:38:51 web.1     |   User Load (0.3ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
11:38:51 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 15 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
11:38:51 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 14 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
11:38:51 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 13 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
11:38:51 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 12 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
11:38:51 web.1     |    (0.2ms)  SELECT COUNT(*) FROM "rates"  WHERE "rates"."rater_id" = $1 AND "rates"."dimension" = 'quality' AND "rates"."rateable_id" = 11 AND "rates"."rateable_type" = 'Bar'  [["rater_id", 1]]
11:38:51 web.1     |   Rendered routes/show.html.erb within layouts/application (8.9ms)
11:38:51 web.1     | Completed 200 OK in 142ms (Views: 130.0ms | ActiveRecord: 3.3ms)

ActiveRecord performance was from 11.9ms to 3.3ms
´´´