Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
1f682bf0
Commit
1f682bf0
authored
Mar 01, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
04797778
d860ab19
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
56 additions
and
48 deletions
+56
-48
app/finders/issuable_finder.rb
app/finders/issuable_finder.rb
+25
-15
changelogs/unreleased/54643-lower_issuable_finder_complexity.yml
...ogs/unreleased/54643-lower_issuable_finder_complexity.yml
+5
-0
spec/controllers/groups_controller_spec.rb
spec/controllers/groups_controller_spec.rb
+1
-3
spec/finders/issues_finder_spec.rb
spec/finders/issues_finder_spec.rb
+25
-30
No files found.
app/finders/issuable_finder.rb
View file @
1f682bf0
...
@@ -78,13 +78,15 @@ class IssuableFinder
...
@@ -78,13 +78,15 @@ class IssuableFinder
items
=
init_collection
items
=
init_collection
items
=
filter_items
(
items
)
items
=
filter_items
(
items
)
# This has to be last as we
may
use a CTE as an optimization fence
# This has to be last as we use a CTE as an optimization fence
#
by passing the attempt_group_search_optimizations param and
#
for counts by passing the force_cte param and enabling the
#
enabling the use_cte_for_group_issues_search
feature flag
#
attempt_group_search_optimizations
feature flag
# https://www.postgresql.org/docs/current/static/queries-with.html
# https://www.postgresql.org/docs/current/static/queries-with.html
items
=
by_search
(
items
)
items
=
by_search
(
items
)
sort
(
items
)
items
=
sort
(
items
)
unless
use_cte_for_count?
items
end
end
def
filter_items
(
items
)
def
filter_items
(
items
)
...
@@ -117,8 +119,9 @@ class IssuableFinder
...
@@ -117,8 +119,9 @@ class IssuableFinder
#
#
# rubocop: disable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def
count_by_state
def
count_by_state
count_params
=
params
.
merge
(
state:
nil
,
sort:
nil
)
count_params
=
params
.
merge
(
state:
nil
,
sort:
nil
,
force_cte:
true
)
finder
=
self
.
class
.
new
(
current_user
,
count_params
)
finder
=
self
.
class
.
new
(
current_user
,
count_params
)
counts
=
Hash
.
new
(
0
)
counts
=
Hash
.
new
(
0
)
# Searching by label includes a GROUP BY in the query, but ours will be last
# Searching by label includes a GROUP BY in the query, but ours will be last
...
@@ -128,8 +131,11 @@ class IssuableFinder
...
@@ -128,8 +131,11 @@ class IssuableFinder
#
#
# This does not apply when we are using a CTE for the search, as the labels
# This does not apply when we are using a CTE for the search, as the labels
# GROUP BY is inside the subquery in that case, so we set labels_count to 1.
# GROUP BY is inside the subquery in that case, so we set labels_count to 1.
#
# We always use CTE when searching in Groups if the feature flag is enabled,
# but never when searching in Projects.
labels_count
=
label_names
.
any?
?
label_names
.
count
:
1
labels_count
=
label_names
.
any?
?
label_names
.
count
:
1
labels_count
=
1
if
use_cte_for_
search
?
labels_count
=
1
if
use_cte_for_
count
?
finder
.
execute
.
reorder
(
nil
).
group
(
:state
).
count
.
each
do
|
key
,
value
|
finder
.
execute
.
reorder
(
nil
).
group
(
:state
).
count
.
each
do
|
key
,
value
|
counts
[
count_key
(
key
)]
+=
value
/
labels_count
counts
[
count_key
(
key
)]
+=
value
/
labels_count
...
@@ -305,27 +311,31 @@ class IssuableFinder
...
@@ -305,27 +311,31 @@ class IssuableFinder
def
use_subquery_for_search?
def
use_subquery_for_search?
strong_memoize
(
:use_subquery_for_search
)
do
strong_memoize
(
:use_subquery_for_search
)
do
attempt_group_search_optimizations?
&&
!
force_cte?
&&
attempt_group_search_optimizations?
Feature
.
enabled?
(
:use_subquery_for_group_issues_search
,
default_enabled:
true
)
end
end
end
end
def
use_cte_for_search?
def
use_cte_for_count?
strong_memoize
(
:use_cte_for_search
)
do
strong_memoize
(
:use_cte_for_count
)
do
attempt_group_search_optimizations?
&&
force_cte?
&&
attempt_group_search_optimizations?
!
use_subquery_for_search?
&&
Feature
.
enabled?
(
:use_cte_for_group_issues_search
,
default_enabled:
true
)
end
end
end
end
private
private
def
force_cte?
!!
params
[
:force_cte
]
end
def
init_collection
def
init_collection
klass
.
all
klass
.
all
end
end
def
attempt_group_search_optimizations?
def
attempt_group_search_optimizations?
search
&&
Gitlab
::
Database
.
postgresql?
&&
params
[
:attempt_group_search_optimizations
]
search
&&
Gitlab
::
Database
.
postgresql?
&&
params
[
:attempt_group_search_optimizations
]
&&
Feature
.
enabled?
(
:attempt_group_search_optimizations
,
default_enabled:
true
)
end
end
def
count_key
(
value
)
def
count_key
(
value
)
...
@@ -411,7 +421,7 @@ class IssuableFinder
...
@@ -411,7 +421,7 @@ class IssuableFinder
def
by_search
(
items
)
def
by_search
(
items
)
return
items
unless
search
return
items
unless
search
if
use_cte_for_
search
?
if
use_cte_for_
count
?
cte
=
Gitlab
::
SQL
::
RecursiveCTE
.
new
(
klass
.
table_name
)
cte
=
Gitlab
::
SQL
::
RecursiveCTE
.
new
(
klass
.
table_name
)
cte
<<
items
cte
<<
items
...
...
changelogs/unreleased/54643-lower_issuable_finder_complexity.yml
0 → 100644
View file @
1f682bf0
---
title
:
Speed up group issue search counts
merge_request
:
25411
author
:
type
:
performance
spec/controllers/groups_controller_spec.rb
View file @
1f682bf0
...
@@ -259,9 +259,7 @@ describe GroupsController do
...
@@ -259,9 +259,7 @@ describe GroupsController do
context
'searching'
do
context
'searching'
do
before
do
before
do
# Remove in https://gitlab.com/gitlab-org/gitlab-ce/issues/54643
stub_feature_flags
(
attempt_group_search_optimizations:
true
)
stub_feature_flags
(
use_cte_for_group_issues_search:
false
)
stub_feature_flags
(
use_subquery_for_group_issues_search:
true
)
end
end
it
'works with popularity sort'
do
it
'works with popularity sort'
do
...
...
spec/finders/issues_finder_spec.rb
View file @
1f682bf0
...
@@ -813,7 +813,7 @@ describe IssuesFinder do
...
@@ -813,7 +813,7 @@ describe IssuesFinder do
before
do
before
do
allow
(
Gitlab
::
Database
).
to
receive
(
:postgresql?
).
and_return
(
true
)
allow
(
Gitlab
::
Database
).
to
receive
(
:postgresql?
).
and_return
(
true
)
stub_feature_flags
(
use_subquery_for_group_issues_search
:
true
)
stub_feature_flags
(
attempt_group_search_optimizations
:
true
)
end
end
context
'when there is no search param'
do
context
'when there is no search param'
do
...
@@ -844,11 +844,11 @@ describe IssuesFinder do
...
@@ -844,11 +844,11 @@ describe IssuesFinder do
end
end
end
end
context
'when the
use_subquery_for_group_issues_search
flag is disabled'
do
context
'when the
attempt_group_search_optimizations
flag is disabled'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
before
do
before
do
stub_feature_flags
(
use_subquery_for_group_issues_search
:
false
)
stub_feature_flags
(
attempt_group_search_optimizations
:
false
)
end
end
it
'returns false'
do
it
'returns false'
do
...
@@ -856,6 +856,14 @@ describe IssuesFinder do
...
@@ -856,6 +856,14 @@ describe IssuesFinder do
end
end
end
end
context
'when force_cte? is true'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
,
force_cte:
true
}
}
it
'returns false'
do
expect
(
finder
.
use_subquery_for_search?
).
to
be_falsey
end
end
context
'when all conditions are met'
do
context
'when all conditions are met'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
...
@@ -865,72 +873,59 @@ describe IssuesFinder do
...
@@ -865,72 +873,59 @@ describe IssuesFinder do
end
end
end
end
describe
'#use_cte_for_
search
?'
do
describe
'#use_cte_for_
count
?'
do
let
(
:finder
)
{
described_class
.
new
(
nil
,
params
)
}
let
(
:finder
)
{
described_class
.
new
(
nil
,
params
)
}
before
do
before
do
allow
(
Gitlab
::
Database
).
to
receive
(
:postgresql?
).
and_return
(
true
)
allow
(
Gitlab
::
Database
).
to
receive
(
:postgresql?
).
and_return
(
true
)
stub_feature_flags
(
use_cte_for_group_issues_search:
true
)
stub_feature_flags
(
attempt_group_search_optimizations:
true
)
stub_feature_flags
(
use_subquery_for_group_issues_search:
false
)
end
end
context
'when there is no search param'
do
context
'when there is no search param'
do
let
(
:params
)
{
{
attempt_group_search_optimizations:
true
}
}
let
(
:params
)
{
{
attempt_group_search_optimizations:
true
,
force_cte:
true
}
}
it
'returns false'
do
it
'returns false'
do
expect
(
finder
.
use_cte_for_
search
?
).
to
be_falsey
expect
(
finder
.
use_cte_for_
count
?
).
to
be_falsey
end
end
end
end
context
'when the database is not Postgres'
do
context
'when the database is not Postgres'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
let
(
:params
)
{
{
search:
'foo'
,
force_cte:
true
,
attempt_group_search_optimizations:
true
}
}
before
do
before
do
allow
(
Gitlab
::
Database
).
to
receive
(
:postgresql?
).
and_return
(
false
)
allow
(
Gitlab
::
Database
).
to
receive
(
:postgresql?
).
and_return
(
false
)
end
end
it
'returns false'
do
it
'returns false'
do
expect
(
finder
.
use_cte_for_
search
?
).
to
be_falsey
expect
(
finder
.
use_cte_for_
count
?
).
to
be_falsey
end
end
end
end
context
'when the
attempt_group_search_optimizations
param is falsey'
do
context
'when the
force_cte
param is falsey'
do
let
(
:params
)
{
{
search:
'foo'
}
}
let
(
:params
)
{
{
search:
'foo'
}
}
it
'returns false'
do
it
'returns false'
do
expect
(
finder
.
use_cte_for_search?
).
to
be_falsey
expect
(
finder
.
use_cte_for_count?
).
to
be_falsey
end
end
context
'when the use_cte_for_group_issues_search flag is disabled'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
before
do
stub_feature_flags
(
use_cte_for_group_issues_search:
false
)
end
it
'returns false'
do
expect
(
finder
.
use_cte_for_search?
).
to
be_falsey
end
end
end
end
context
'when
use_subquery_for_search? is true
'
do
context
'when
the attempt_group_search_optimizations flag is disabled
'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
let
(
:params
)
{
{
search:
'foo'
,
force_cte:
true
,
attempt_group_search_optimizations:
true
}
}
before
do
before
do
stub_feature_flags
(
use_subquery_for_group_issues_search:
tru
e
)
stub_feature_flags
(
attempt_group_search_optimizations:
fals
e
)
end
end
it
'returns false'
do
it
'returns false'
do
expect
(
finder
.
use_cte_for_
search
?
).
to
be_falsey
expect
(
finder
.
use_cte_for_
count
?
).
to
be_falsey
end
end
end
end
context
'when all conditions are met'
do
context
'when all conditions are met'
do
let
(
:params
)
{
{
search:
'foo'
,
attempt_group_search_optimizations:
true
}
}
let
(
:params
)
{
{
search:
'foo'
,
force_cte:
true
,
attempt_group_search_optimizations:
true
}
}
it
'returns true'
do
it
'returns true'
do
expect
(
finder
.
use_cte_for_
search
?
).
to
be_truthy
expect
(
finder
.
use_cte_for_
count
?
).
to
be_truthy
end
end
end
end
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment