Skip to content

Commit 8fa5cc0

Browse files
Tales da Aparecidamchehab
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 1455a92 commit 8fa5cc0

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
@@ -308,25 +307,31 @@ def with_tag_counts(self, project=None):
308307
# Project, and share the project.tags cache between all patch.project
309308
# references.
310309
qs = self.prefetch_related('project')
311-
select = OrderedDict()
312-
select_params = []
313310

314311
# All projects have the same tags, so we're good to go here
315312
if project:
316313
tags = project.tags
317314
else:
318315
tags = Tag.objects.all()
319316

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

329-
return qs.extra(select=select, select_params=select_params)
334+
return qs
330335

331336

332337
class PatchManager(models.Manager):

0 commit comments

Comments
 (0)