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

Use size instead of count for has many field #266

Conversation

BenMorganIO
Copy link
Collaborator

To help improve the admin performance, I noticed that there was a long string of #count queries going on; see before for the issue. The odd part to me was that I was doing this in my code: Course.includes(:videos) and yet there was a constant call to #count going on. Since the AR association is already loaded, why go back to PG? Switched from using #count to #size so that AR can intelligently load up the data and call count if its not there or, if it is there, just use ruby.

Before:

17:50:43 web.1    | Started GET "/admin/courses" for ::1 at 2015-11-21 17:50:43 -0800
17:50:43 web.1    | Processing by Admin::CoursesController#index as HTML
17:50:43 web.1    |   Course Load (0.4ms)  SELECT  "courses".* FROM "courses" LIMIT 20 OFFSET 0
17:50:43 web.1    |   Video Load (0.4ms)  SELECT "videos".* FROM "videos" WHERE "videos"."course_id" IN (13, 14, 15, 16)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.1ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.1ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.0ms)
17:50:43 web.1    |    (0.2ms)  SELECT COUNT(*) FROM "videos" WHERE "videos"."course_id" = $1  [["course_id", 13]]
17:50:43 web.1    |   Rendered fields/has_many/_index.html.erb (0.8ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.0ms)
17:50:43 web.1    |    (0.2ms)  SELECT COUNT(*) FROM "videos" WHERE "videos"."course_id" = $1  [["course_id", 14]]
17:50:43 web.1    |   Rendered fields/has_many/_index.html.erb (1.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.0ms)
17:50:43 web.1    |    (0.1ms)  SELECT COUNT(*) FROM "videos" WHERE "videos"."course_id" = $1  [["course_id", 15]]
17:50:43 web.1    |   Rendered fields/has_many/_index.html.erb (0.8ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.0ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.1ms)
17:50:43 web.1    |    (0.1ms)  SELECT COUNT(*) FROM "videos" WHERE "videos"."course_id" = $1  [["course_id", 16]]
17:50:43 web.1    |   Rendered fields/has_many/_index.html.erb (0.9ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_collection.html.erb (45.2ms)
17:50:43 web.1    |    (0.3ms)  SELECT COUNT(*) FROM "courses"
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/index.html.erb within layouts/administrate/application (59.9ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_sidebar.html.erb (0.7ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_flashes.html.erb (0.1ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_javascript.html.erb (53.1ms)
17:50:43 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/layouts/administrate/application.html.erb (187.3ms)
17:50:43 web.1    | Completed 200 OK in 205ms (Views: 202.2ms | ActiveRecord: 1.7ms)

After:

17:51:21 web.1    | Started GET "/admin/courses" for ::1 at 2015-11-21 17:51:21 -0800
17:51:21 web.1    | Processing by Admin::CoursesController#index as HTML
17:51:21 web.1    |   Course Load (0.4ms)  SELECT  "courses".* FROM "courses" LIMIT 20 OFFSET 0
17:51:21 web.1    |   Video Load (0.4ms)  SELECT "videos".* FROM "videos" WHERE "videos"."course_id" IN (13, 14, 15, 16)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered fields/has_many/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered fields/has_many/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered fields/has_many/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/number/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/string/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/fields/text/_index.html.erb (0.0ms)
17:51:21 web.1    |   Rendered fields/has_many/_index.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_collection.html.erb (41.2ms)
17:51:21 web.1    |    (0.2ms)  SELECT COUNT(*) FROM "courses"
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/index.html.erb within layouts/administrate/application (55.5ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_sidebar.html.erb (0.8ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_flashes.html.erb (0.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/administrate/application/_javascript.html.erb (51.1ms)
17:51:21 web.1    |   Rendered /Users/BenAMorgan/.rvm/gems/ruby-2.2.3/bundler/gems/administrate-a14e388bed54/app/views/layouts/administrate/application.html.erb (182.7ms)
17:51:21 web.1    | Completed 200 OK in 201ms (Views: 198.6ms | ActiveRecord: 1.0ms)

Reference: http://batsov.com/articles/2014/02/17/the-elements-of-style-in-ruby-number-13-length-vs-size-vs-count/

@BenMorganIO BenMorganIO force-pushed the use-size-instead-of-count-for-has-many-field branch from 4036cdd to 9a1acd1 Compare November 22, 2015 01:53
@c-lliope
Copy link
Contributor

This looks good to me! I want to take a look and see if there are any other places we can make this change, but it should be about good to go.

@BenMorganIO
Copy link
Collaborator Author

@Graysonwright 👍

I think there's a few other instances where #count is used. I actually updated them, but it ended up breaking tests. For now, this passes and adds an optimization.

@c-lliope
Copy link
Contributor

c-lliope commented Dec 3, 2015

Great! I'm going to merge this as soon as I get off my flight tomorrow.

@c-lliope
Copy link
Contributor

c-lliope commented Dec 5, 2015

Waiting on #294.

@c-lliope
Copy link
Contributor

c-lliope commented Dec 7, 2015

Merged in as fd490db. Thanks!

@c-lliope c-lliope closed this Dec 7, 2015
@BenMorganIO BenMorganIO deleted the use-size-instead-of-count-for-has-many-field branch December 7, 2015 05:17
c-lliope added a commit that referenced this pull request Dec 9, 2015
Changes:

```
* [#251] [FEATURE] Raise a helpful error when an attribute is missing from
  `ATTRIBUTE_TYPES`
* [#298] [FEATURE] Support ActiveRecord model I18n translations
* [#312] [FEATURE] Add a `nil` option to `belongs_to` form fields
* [#231] [UI] Fix layout issue on show page where a long label next to an empty
  value would cause following fields on the page to be mis-aligned.
* [#309] [UI] Fix layout issue in datetime pickers where months and years
  would not wrap correctly.
* [#306] [UI] Wrap long text lines (on word breaks) on show pages
* [#214] [UI] Improve header layout when there is a long page title
* [#198] [UI] Improve spacing around bottom link in sidebar
* [#206] [UI] Left-align checkboxes in boolean form fields
* [#315] [UI] Remove the `IDS` suffix for `HasMany` form field labels
* [#259] [BUGFIX] Make installation generator more robust
  by ignoring dynamically generated, unnamed models
* [#243] [BUGFIX] Fix up a "Show" button on the edit page that was not using the
  `display_resource` method.
* [#248] [BUGFIX] Improve polymorphic relationship's dashboard class detection.
* [#247] [BUGFIX] Populate `has_many` and `belongs_to` select boxes
  with the current value of the relationship.
* [#217] [I18n] Dutch
* [#263] [I18n] Swedish
* [#272] [I18n] Danish
* [#270] [I18n] Don't apologize about missing relationship support.
* [#237] [I18n] Fix broken paths for several I18n files (de, es, fr, pt-BR, vi).
* [#266] [OPTIM] Save a few database queries by using cached counts
```
@ACPK
Copy link

ACPK commented Jan 12, 2017

@Graysonwright - I get "ActionView::Template::Error: undefined method `size' for nil:NilClass".

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.

3 participants