From 5f77a024cba5d20f65b4c280d0cdb943c49cb762 Mon Sep 17 00:00:00 2001 From: Stephan Kulow Date: Thu, 20 Dec 2018 18:27:29 +0100 Subject: [PATCH] Avoid N+1 queries in update policy has_remote_repositories? is called from project update? policy, which is called in a lot of places. And it's horribly slow as it loops through an array with N+1 queries looking like this in logs: DownloadRepository Exists (0.1ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 357782 LIMIT 1 DownloadRepository Exists (0.2ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 157220 LIMIT 1 DownloadRepository Exists (0.1ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 214402 LIMIT 1 DownloadRepository Exists (0.1ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 289102 LIMIT 1 DownloadRepository Exists (0.1ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 264047 LIMIT 1 DownloadRepository Exists (0.1ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 320882 LIMIT 1 DownloadRepository Exists (0.1ms) SELECT 1 AS one FROM `download_repositories` WHERE `download_repositories`.`repository_id` = 408379 LIMIT 1 Using one subselect gives you one access into the repositories index. p=Project.find_by_name('openSUSE:Tools') irb(main):022:0> Benchmark.measure { 100.times { p.has_remote_repositories_old? } } => real=2.6102131991647184 irb(main):023:0> Benchmark.measure { 100.times { p.has_remote_repositories? } } => real=0.0647597061470151 --- src/api/app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/app/models/project.rb b/src/api/app/models/project.rb index 3dae4271f9d..a3070d52a8b 100644 --- a/src/api/app/models/project.rb +++ b/src/api/app/models/project.rb @@ -1586,7 +1586,7 @@ def self.remove_repositories(repositories, opts = {}) end def has_remote_repositories? - repositories.any? { |r| r.download_repositories.any? } + DownloadRepository.where(repository_id: repositories.select(:id)).exists? end def api_obj