Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegate the Mentor's journal month_count to the DB #138

Merged
merged 1 commit into from
Feb 7, 2016

Conversation

pmukerji
Copy link
Contributor

@pmukerji pmukerji commented Jan 8, 2016

Instead of loading the records to Ruby, interpolating and counting - the calculation is done in the DB directly using DISTINCT.

See rails/rails#5554 for why #select is used (issue with counting distinct on multiple columns)

SQL Explains on two possible queries:

1

Journal.unscoped.where(mentor_id: id).select('DISTINCT (month, year)').count

results in:

future_kids_development=# explain SELECT COUNT(DISTINCT (month, year)) FROM "journals" WHERE "journals"."mentor_id" = 1;
                                           QUERY PLAN
------------------------------------------------------------------------------------------------
 Aggregate  (cost=9.51..9.52 rows=1 width=8)
   ->  Bitmap Heap Scan on journals  (cost=4.16..9.50 rows=2 width=8)
         Recheck Cond: (mentor_id = 1)
         ->  Bitmap Index Scan on index_journals_on_mentor_id  (cost=0.00..4.16 rows=2 width=0)
               Index Cond: (mentor_id = 1)

2

Maybe a more readable approach is using the relationship directly:

journals.select('DISTINCT (month, year)').count
future_kids_development=# explain SELECT COUNT(DISTINCT (month, year)) FROM "journals" INNER JOIN "kids" ON "kids"."id" = "journals"."kid_id" WHERE "journals"."mentor_id" = 1;                                                 QUERY PLAN
------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=20.78..20.79 rows=1 width=8)
   ->  Hash Join  (cost=9.53..20.78 rows=1 width=8)
         Hash Cond: (kids.id = journals.kid_id)
         ->  Seq Scan on kids  (cost=0.00..10.90 rows=90 width=4)
         ->  Hash  (cost=9.50..9.50 rows=2 width=12)
               ->  Bitmap Heap Scan on journals  (cost=4.16..9.50 rows=2 width=12)
                     Recheck Cond: (mentor_id = 1)
                     ->  Bitmap Index Scan on index_journals_on_mentor_id  (cost=0.00..4.16 rows=2 width=0)
                           Index Cond: (mentor_id = 1)

Both work but with the second it looks like the cost is higher since you get this unnecessary join when you don't remove the default scope of Journal.

Instead of loading the records to Ruby, interpolating and counting
the calculation is done in the DB directly
@pmukerji pmukerji changed the title Delegate a Journal Month Count to the DB Delegate the Mentor's journal month_count to the DB Jan 8, 2016
panterch added a commit that referenced this pull request Feb 7, 2016
Delegate the Mentor's journal month_count to the DB
@panterch panterch merged commit 4dd4dfc into panterch:master Feb 7, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants