Project

General

Profile

Actions

Feature #44405

open

Reduce repeated SQL queries caused by User#is_or_belongs_to? when issues are assigned to groups

Added by Go MAEDA 2 days ago. Updated about 4 hours ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
Performance
Target version:
Resolution:

Description

User#is_or_belongs_to? checks group membership with arg.users.include?(self), which runs a SQL query against groups_users on every call because the association is not loaded. The attached patch replaces it with group_ids.include?(arg.id), so the group ids are loaded once per user and reused for subsequent checks.

Examples of operations affected by this:

  • Viewing an issue as a user whose role can only see issues they are author or assignee of (or a private issue with the default visibility): Issue#visible? issues one groups_users query for each group-assigned related issue and #123 link on the page.
  • Collecting notification recipients after an issue update: User#notify_about? checks both the assignee and the previous assignee, so reassigning an issue between groups issues two queries per candidate user.

Both expressions read the same groups_users table, so the behavior is unchanged. In a benchmark checking visible? for 500 group-assigned issues, queries on groups_users dropped from 500 to 1 and total time was reduced by about 40%.

For example, checking two private issues assigned to different groups runs two queries before the patch:

  User Exists? (0.7ms)  SELECT 1 AS one FROM `users` INNER JOIN `groups_users` ON `users`.`id` = `groups_users`.`user_id` WHERE `users`.`type` = 'User' AND `groups_users`.`group_id` = 10 AND `users`.`id` = 3 LIMIT 1
  User Exists? (0.5ms)  SELECT 1 AS one FROM `users` INNER JOIN `groups_users` ON `users`.`id` = `groups_users`.`user_id` WHERE `users`.`type` = 'User' AND `groups_users`.`group_id` = 11 AND `users`.`id` = 3 LIMIT 1

After the patch, the group ids are loaded once and subsequent checks require no queries:

  Group Pluck (0.5ms)  SELECT `users`.`id` FROM `users` INNER JOIN `groups_users` ON `users`.`id` = `groups_users`.`group_id` WHERE `users`.`type` IN ('Group', 'GroupBuiltin', 'GroupAnonymous') AND `groups_users`.`user_id` = 3

Files

Actions #1

Updated by Go MAEDA about 4 hours ago

  • Target version set to 7.1.0

Setting the target version to 7.1.0.

Actions

Also available in: Atom PDF