Skip to content

Optimize hosts controller query: use pluck instead of map for hostgroup_ids#10951

Open
raman1236 wants to merge 1 commit into
theforeman:developfrom
raman1236:fix/database-query-optimizations
Open

Optimize hosts controller query: use pluck instead of map for hostgroup_ids#10951
raman1236 wants to merge 1 commit into
theforeman:developfrom
raman1236:fix/database-query-optimizations

Conversation

@raman1236
Copy link
Copy Markdown

@raman1236 raman1236 commented Apr 6, 2026

Description

Optimize database query in hosts controller to reduce unnecessary memory allocation.

Change

app/controllers/hosts_controller.rb - Use pluck instead of map

# Before
@hosts.map(&:hostgroup_id).compact.uniq

# After
@hosts.pluck(:hostgroup_id).compact.uniq

map(&:hostgroup_id) loads all Host ActiveRecord objects into memory and extracts the attribute in Ruby. pluck(:hostgroup_id) generates a SELECT hostgroup_id FROM ... query that returns only the needed column values directly from the database, avoiding unnecessary object instantiation. This is particularly impactful on the hosts index page which can display many hosts.

Note on previous user.rb change

The original PR also included a .where().any?.exists?() change in user.rb. As correctly pointed out by @adamruzicka, Rails already optimizes .any? to generate the same efficient SELECT 1 AS one ... LIMIT 1 query, so that change was reverted.

Copy link
Copy Markdown
Member

@ofedoren ofedoren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @raman1236, it'll need a ticket (https://projects.theforeman.org/projects/foreman/issues/new) and then updated commit message with the ticket's number. Otherwise LGTM.

@stejskalleos stejskalleos self-assigned this Apr 7, 2026
@adamruzicka
Copy link
Copy Markdown
Contributor

where(:id => id).any? generates SELECT "auth_sources".* FROM "auth_sources" WHERE ... and loads matching records into memory before checking presence. exists?(id) generates SELECT 1 AS one FROM "auth_sources" WHERE ... LIMIT 1 which is more efficient as it stops after finding one match and doesn't instantiate ActiveRecord objects. This runs on every user update validation.

Does it though?

> AuthSourceHidden.where(:id => 4).any?
2026-04-08T11:01:12 [D|sql|]   AuthSourceHidden Exists? (1.7ms)  SELECT 1 AS one FROM "auth_sources" WHERE "auth_sources"."type" = $1 AND "auth_sources"."id" = $2 LIMIT $3  [["type", "AuthSourceHidden"], ["id", 4], ["LIMIT", 1]]

> AuthSourceHidden.exists?(4)
2026-04-08T11:01:01 [D|sql|]   AuthSourceHidden Exists? (4.7ms)  SELECT 1 AS one FROM "auth_sources" WHERE "auth_sources"."type" = $1 AND "auth_sources"."id" = $2 LIMIT $3  [["type", "AuthSourceHidden"], ["id", 4], ["LIMIT", 1]]

@raman1236
Copy link
Copy Markdown
Author

@adamruzicka Great catch — you're absolutely right! I tested this myself and confirmed that Rails' .any? already generates the optimized SELECT 1 AS one ... LIMIT 1 query, making it equivalent to .exists? at the SQL level.\n\nI've reverted the user.rb change and updated the PR to focus solely on the pluck vs map optimization in hosts_controller.rb, which does produce a genuinely different (more efficient) query by selecting only the hostgroup_id column instead of loading full ActiveRecord objects.

@raman1236 raman1236 changed the title Optimize database queries in hosts controller and user model Optimize hosts controller query: use pluck instead of map for hostgroup_ids Apr 30, 2026
@raman1236
Copy link
Copy Markdown
Author

Friendly ping — review feedback has been addressed (reverted the user.rb change, kept only the pluck optimization). The PR now focuses on a single targeted optimization in the hosts controller. Would appreciate another look. Thanks!

@stejskalleos
Copy link
Copy Markdown
Contributor

@adamruzicka Great catch — you're absolutely right!

LOL.

@stejskalleos
Copy link
Copy Markdown
Contributor

@raman1236, please squash the commits into one and change the commit message to Fixes #xxx Optimize hosts ... where the #xxx is the ID of the issue in our tracker, thank you.

@raman1236 raman1236 force-pushed the fix/database-query-optimizations branch from e2f2531 to eb2899e Compare May 16, 2026 21:38
@raman1236 raman1236 force-pushed the fix/database-query-optimizations branch from eb2899e to 499a3b5 Compare May 30, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants