Skip to content

Commit 52877f8

Browse files
Tales da Aparecidastephenfin
authored andcommitted
models: optimize with_tag_counts using case-when
Leverage PatchTag index replacing the subquery counter with a JOIN. The current code is too slow on MySQL, as it doesn't use indexes. The new approach is more direct and allows proper index usage. Signed-off-by: Tales da Aparecida <tales.aparecida@redhat.com>
1 parent 035ef32 commit 52877f8

1 file changed

Lines changed: 15 additions & 10 deletions

File tree

patchwork/models.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# SPDX-License-Identifier: GPL-2.0-or-later
66

77
from collections import Counter
8-
from collections import OrderedDict
98
import datetime
109
import random
1110
import re
@@ -312,25 +311,31 @@ def with_tag_counts(self, project=None):
312311
# Project, and share the project.tags cache between all patch.project
313312
# references.
314313
qs = self.prefetch_related('project')
315-
select = OrderedDict()
316-
select_params = []
317314

318315
# All projects have the same tags, so we're good to go here
319316
if project:
320317
tags = project.tags
321318
else:
322319
tags = Tag.objects.all()
323320

321+
# Annotate the count of each Tag in a column
324322
for tag in tags:
325-
select[tag.attr_name] = (
326-
'coalesce('
327-
'(SELECT count FROM patchwork_patchtag'
328-
' WHERE patchwork_patchtag.patch_id=patchwork_patch.id'
329-
' AND patchwork_patchtag.tag_id=%s), 0)'
323+
qs = qs.annotate(
324+
**{
325+
tag.attr_name: models.Sum(
326+
models.Case(
327+
models.When(
328+
patchtag__tag_id=tag.id,
329+
then=models.F('patchtag__count'),
330+
),
331+
default=models.Value(0),
332+
output_field=models.IntegerField(),
333+
)
334+
)
335+
}
330336
)
331-
select_params.append(tag.id)
332337

333-
return qs.extra(select=select, select_params=select_params)
338+
return qs
334339

335340

336341
class PatchManager(models.Manager):

0 commit comments

Comments
 (0)