Commit 344fbdb2 authored by Terri Chu's avatar Terri Chu

Reduce N+1 queries for Search API projects scope

Add new scope for Project model to preload data for
API entities. The scope will be used by the Search
API to preload data when returning Elastic Search
results.

Added tests for projects scope to avoid N+1 issues.
Reorganize merge_requests scope tests.
parent e437426b
......@@ -506,6 +506,10 @@ class Project < ApplicationRecord
left_outer_joins(:pages_metadatum)
.where(project_pages_metadata: { project_id: nil })
end
scope :with_api_entity_associations, -> {
preload(:project_feature, :route, :tags,
group: :ip_restrictions, namespace: [:route, :owner])
}
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
......
---
title: Fix N+1 queries for Elastic Search projects scope.
merge_request: 32688
author:
type: performance
......@@ -68,6 +68,8 @@ describe API::Search do
ensure_elasticsearch_index!
end
it_behaves_like 'pagination', scope: 'merge_requests'
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new { get api(endpoint, user), params: { scope: 'merge_requests', search: '*' } }
......@@ -176,17 +178,6 @@ describe API::Search do
it_behaves_like 'pagination', scope: 'issues'
end
context 'for merge_requests scope', :sidekiq_inline do
before do
create(:merge_request, target_branch: 'feature_2', source_project: project)
create(:merge_request, target_branch: 'feature_3', source_project: project)
ensure_elasticsearch_index!
end
it_behaves_like 'pagination', scope: 'merge_requests'
end
unless level == :project
context 'for projects scope', :sidekiq_inline do
before do
......@@ -197,6 +188,17 @@ describe API::Search do
end
it_behaves_like 'pagination', scope: 'projects'
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new { get api(endpoint, user), params: { scope: 'projects', search: '*' } }
create_list(:project, 3, :public, group: group)
create_list(:project, 4, :public)
ensure_elasticsearch_index!
# Some N+1 queries still exist
expect { get api(endpoint, user), params: { scope: 'projects', search: '*' } }.not_to exceed_query_limit(control.count + 4)
end
end
end
......
......@@ -21,7 +21,8 @@ module API
}.freeze
SCOPE_PRELOAD_METHOD = {
merge_requests: :with_api_entity_associations
merge_requests: :with_api_entity_associations,
projects: :with_api_entity_associations
}.freeze
def search(additional_params = {})
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment