Skip to content

Commit 98a2d05

Browse files
daxtensstephenfin
authored andcommitted
REST: fix patch listing query
The patch listing query is punishingly slow under even very simple filters. The new data model in 3.0 will help _a lot_, so this is a simple fix: I did try indexes but haven't got really deeply into the weeds of what we can do with them. Move a number of things from select_related to prefetch_related: we trade off one big, inefficient query for a slightly larger number of significantly more efficient queries. On my laptop with 2 copies of the canonical kernel team list loaded into the database, and considering only the API view (the JSON view is always faster) with warm caches and considering the entire set of SQL queries: - /api/patches/?project=1 ~1.4-1.5s -> <100ms, something like 14x better - /api/patches/?project=1&since=2010-11-01T00:00:00 ~1.7-1.8s -> <560ms, something like 3x better (now dominated by the counting query only invoked on the HTML API view, not the pure JSON API view.) The things I moved: * project: this was generating SQL that looked like: INNER JOIN `patchwork_project` T5 ON (`patchwork_submission`.`project_id` = T5.`id`) This is correct but we've already had to join the patchwork_submission table and perhaps as a result it seems to be inefficient. * series__project: Likewise we've already had to join the series table, doing another join is possibly why it is inefficient. * delegate: I do not know why this was tanking performance. I think it might relate to the strategy mysql was using. Reported-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org> Signed-off-by: Daniel Axtens <dja@axtens.net> Reviewed-by: Stephen Finucane <stephen@that.guru>
1 parent 97155c0 commit 98a2d05

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

patchwork/api/patch.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,13 @@ class PatchList(ListAPIView):
288288
ordering = 'id'
289289

290290
def get_queryset(self):
291+
# TODO(dja): we need to revisit this after the patch migration, paying
292+
# particular attention to cases with filtering
291293
return Patch.objects.all()\
292-
.prefetch_related('check_set', 'related__patches__project')\
293-
.select_related('project', 'state', 'submitter', 'delegate',
294-
'series__project')\
294+
.prefetch_related(
295+
'check_set', 'delegate', 'project', 'series__project',
296+
'related__patches__project')\
297+
.select_related('state', 'submitter', 'series')\
295298
.defer('content', 'diff', 'headers')
296299

297300

patchwork/tests/api/test_patch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,11 @@ def test_list_version_1_0(self):
211211
self.assertNotIn('web_url', resp.data[0])
212212

213213
def test_list_bug_335(self):
214-
"""Ensure we retrieve the embedded series project once."""
214+
"""Ensure we retrieve the embedded series project in O(1)."""
215215
series = create_series()
216216
create_patches(5, series=series)
217217

218-
with self.assertNumQueries(4):
218+
with self.assertNumQueries(7):
219219
self.client.get(self.api_url())
220220

221221
@utils.store_samples('patch-detail')

0 commit comments

Comments
 (0)