Skip to content

Commit af5c1e8

Browse files
authored
Optimize DISTINCT queries (#4129)
The DISTINCT clause instructs the database to ensure that all returned rows are distinct; so the database compares all returned columns. In most cases we simply want to prevent duplicate entries in the result set which can be achieved by a DISTINCT ON (id) clause that does the comparison on the 'id' column only and is much more efficient (i.e. for large final or even intermediate result sets the database might need to write them to disk to perform the comparison). MySQL does not support DISTINCT ON, but Sequel translates this transparently to GROUP BY. PostgreSQL has the following restriction: SELECT DISTINCT ON expressions must match initial ORDER BY expressions. Thus the SequelPaginator has been enhanced to use the ORDER BY columns also for the DISTINCT ON clause if they are unique (i.e. 'id' or 'guid' included). In case the ORDER BY clause is not unique, DISTINCT is used instead. DISTINCT statements with a single selected column have not been changed.
1 parent da22df3 commit af5c1e8

14 files changed

+90
-24
lines changed

app/controllers/v3/spaces_controller.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,13 @@ def fetch_isolation_segment(guid)
228228
def fetch_running_security_group_guids(space)
229229
space_level_groups = SecurityGroup.where(spaces: space)
230230
global_groups = SecurityGroup.where(running_default: true)
231-
space_level_groups.union(global_groups).map(&:guid)
231+
space_level_groups.union(global_groups).select_map(:guid)
232232
end
233233

234234
def fetch_staging_security_group_guids(space)
235235
space_level_groups = SecurityGroup.where(staging_spaces: space)
236236
global_groups = SecurityGroup.where(staging_default: true)
237-
space_level_groups.union(global_groups).distinct.map(&:guid)
237+
space_level_groups.union(global_groups).distinct.select_map(:guid)
238238
end
239239

240240
def space_not_found!

app/decorators/field_service_instance_broker_decorator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def decorate(hash, service_instances)
2121
join(:service_plans, service_id: :services__id).
2222
join(:service_instances, service_plan_id: :service_plans__id).
2323
where(service_instances__id: managed_service_instances.map(&:id)).
24-
distinct.
24+
distinct(:service_brokers__created_at, :service_brokers__guid).
2525
order_by(:service_brokers__created_at, :service_brokers__guid).
2626
select(:service_brokers__name, :service_brokers__guid, :service_brokers__created_at).
2727
all

app/decorators/field_service_instance_offering_decorator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def decorate(hash, service_instances)
2020
join(:service_plans, service_id: :services__id).
2121
join(:service_instances, service_plan_id: :service_plans__id).
2222
where(service_instances__id: managed_service_instances.map(&:id)).
23-
distinct.
23+
distinct(:services__created_at, :services__guid).
2424
order_by(:services__created_at, :services__guid).
2525
select(:services__label, :services__guid, :services__description, :services__tags, :services__extra, :services__service_broker_id, :services__created_at).
2626
all

app/fetchers/base_service_list_fetcher.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def distinct_union(_dataset)
161161
def join_plan_org_visibilities(dataset)
162162
dataset = join_service_plans(dataset)
163163
dataset = join(dataset, :inner, :service_plan_visibilities, service_plan_id: Sequel[:service_plans][:id])
164-
dataset.distinct # service plans can have multiple visibilities
164+
distinct(dataset) # service plans can have multiple visibilities
165165
end
166166

167167
def join_service_brokers(dataset)
@@ -187,13 +187,13 @@ def join_broker_orgs(dataset)
187187
def join_plan_spaces(dataset)
188188
dataset = join_plan_orgs(dataset)
189189
dataset = join(dataset, :inner, Sequel[:spaces].as(:plan_spaces), organization_id: Sequel[:plan_orgs][:id])
190-
dataset.distinct # organizations can have multiple spaces
190+
distinct(dataset) # organizations can have multiple spaces
191191
end
192192

193193
def join_service_instances(dataset)
194194
dataset = join_service_plans(dataset)
195195
dataset = join(dataset, :inner, :service_instances, service_plan_id: Sequel[:service_plans][:id])
196-
dataset.distinct # service plans can have multiple instances
196+
distinct(dataset) # service plans can have multiple instances
197197
end
198198

199199
def join(dataset, type, table, on)
@@ -202,6 +202,10 @@ def join(dataset, type, table, on)
202202
end
203203
dataset.join_table(type, table, on)
204204
end
205+
206+
def distinct(dataset)
207+
dataset.distinct(Sequel.qualify(dataset.model.table_name, :id))
208+
end
205209
end
206210
end
207211
end

app/fetchers/organization_quota_list_fetcher.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def filter(message, dataset, readable_org_guids_query=nil)
2323
if message.requested? :organization_guids
2424
dataset = dataset.
2525
join(:organizations, quota_definition_id: :id).
26-
where(organizations__guid: message.organization_guids).distinct.
26+
where(organizations__guid: message.organization_guids).distinct(:id).
2727
qualify(:quota_definitions)
2828

2929
dataset = dataset.where(organizations__guid: readable_org_guids_query) if readable_org_guids_query

app/fetchers/service_instance_list_fetcher.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def fetch(message, omniscient: false, readable_spaces_dataset: nil, eager_loaded
2323

2424
filter(dataset, message).
2525
select_all(:service_instances).
26-
distinct
26+
distinct(:service_instances__id)
2727
end
2828

2929
private

app/fetchers/service_offering_list_fetcher.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def filter(message, dataset, klass)
3333

3434
def join_service_plans(dataset)
3535
dataset = join(dataset, :inner, :service_plans, service_id: Sequel[:services][:id])
36-
dataset.distinct # services can have multiple plans
36+
distinct(dataset) # services can have multiple plans
3737
end
3838

3939
def join_services(dataset)
@@ -43,7 +43,7 @@ def join_services(dataset)
4343
def distinct_union(dataset)
4444
# The UNIONed :services datasets (permissions granted on org level for plans / permissions
4545
# granted on space level for brokers / public plans) might contain duplicate entries.
46-
dataset.distinct
46+
distinct(dataset)
4747
end
4848
end
4949
end

app/fetchers/service_plan_visibility_fetcher.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def orgs_query(service_plan_guids:)
2424

2525
dataset.
2626
select_all(:organizations).
27-
distinct.
27+
distinct(:organizations__id).
2828
order_by(:id)
2929
end
3030
end

app/fetchers/space_quota_list_fetcher.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def filter(message, dataset, readable_space_quota_guids)
2525
if message.requested? :space_guids
2626
dataset = dataset.
2727
join(:spaces, space_quota_definition_id: :id).
28-
where(Sequel[:spaces][:guid] => message.space_guids).distinct.
28+
where(Sequel[:spaces][:guid] => message.space_guids).distinct(:id).
2929
qualify(:space_quota_definitions)
3030
end
3131

app/jobs/runtime/prune_completed_builds.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def perform
1313
logger.info('Cleaning up old builds')
1414

1515
guids_for_apps_with_builds = BuildModel.
16-
distinct(:app_guid).
17-
map(&:app_guid)
16+
distinct.
17+
select_map(:app_guid)
1818

1919
guids_for_apps_with_builds.each do |app_guid|
2020
builds_dataset = BuildModel.where(app_guid:)

0 commit comments

Comments
 (0)