Avoid DISTINCT on COUNT queries when possible #55029
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation / Background
Fixes #55027
When calling
.count
on an eager-loaded query where the base tablebelongs_to
the eager-loaded table, AR switchesCOUNT(*)
to aCOUNT(DISTINCT "id")
. However, this is unnecessary as there will never be duplicates in abelongs_to
relationship like this.This isn't normally an issue, but when running COUNT queries on larger tables (at least in Postgres), I've seen this turn ~100ms queries into ~30s queries.
This Pull Request has been created because a very common scenario is paginating data that might have an
order
clause on an included table, which is then paginated with gems like Kaminari that will callcount
on the relation without additional reworking of the query. e.g.:Detail
This Pull Request changes ActiveRecord's Calculation logic around COUNT queries to only add a
DISTINCT
column when any eager-loaded associations are not belongs_to associations.Additional information
One workaround we've used is to avoid the eager-load and just change the query to:
This works fine, but we lose the eager-loaded
post
association in doing so.Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]