Add submission indexes to optimize user_problems

This commit is contained in:
cuom1999 2023-03-07 19:59:12 -06:00
parent ec2c2ccf13
commit d2f261acfe
3 changed files with 64 additions and 41 deletions

View file

@ -0,0 +1,27 @@
# Generated by Django 3.2.18 on 2023-03-08 01:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("judge", "0153_drop_comment_page"),
]
operations = [
migrations.AddIndex(
model_name="submission",
index=models.Index(
fields=["problem", "user", "-points"],
name="judge_submi_problem_5687ea_idx",
),
),
migrations.AddIndex(
model_name="submission",
index=models.Index(
fields=["contest_object", "problem", "user", "-points"],
name="judge_submi_contest_31cdbb_idx",
),
),
]

View file

@ -233,6 +233,11 @@ class Submission(models.Model):
verbose_name = _("submission") verbose_name = _("submission")
verbose_name_plural = _("submissions") verbose_name_plural = _("submissions")
indexes = [
models.Index(fields=["problem", "user", "-points"]),
models.Index(fields=["contest_object", "problem", "user", "-points"]),
]
class SubmissionSource(models.Model): class SubmissionSource(models.Model):
submission = models.OneToOneField( submission = models.OneToOneField(

View file

@ -21,49 +21,40 @@ PPBreakdown = namedtuple(
def get_pp_breakdown(user, start=0, end=settings.DMOJ_PP_ENTRIES): def get_pp_breakdown(user, start=0, end=settings.DMOJ_PP_ENTRIES):
with connection.cursor() as cursor: with connection.cursor() as cursor:
cursor.execute( cursor.execute(
""" f"""
SELECT submission.problem_code, SELECT max_points_table.problem_code,
submission.problem_name, max_points_table.problem_name,
submission.max_points, max_points_table.max_points,
submission.sub_id, judge_submission.id,
submission.sub_date, judge_submission.date,
submission.case_points, judge_submission.case_points,
submission.case_total, judge_submission.case_total,
submission.result, judge_submission.result,
judge_language.short_name, judge_language.short_name,
judge_language.key judge_language.key
FROM FROM (
(SELECT max_points_table.problem_code problem_code,
max_points_table.problem_name problem_name,
max_points_table.max_points max_points,
judge_submission.id sub_id,
judge_submission.date sub_date,
judge_submission.case_points case_points,
judge_submission.case_total case_total,
judge_submission.result result,
judge_submission.language_id language_id
FROM judge_submission
JOIN (
SELECT judge_problem.id problem_id, SELECT judge_problem.id problem_id,
judge_problem.name problem_name, judge_problem.name problem_name,
judge_problem.code problem_code, judge_problem.code problem_code,
MAX(judge_submission.points) AS max_points MAX(judge_submission.points) AS max_points
FROM judge_problem FROM judge_problem
INNER JOIN judge_submission INNER JOIN judge_submission ON (judge_problem.id = judge_submission.problem_id)
ON (judge_problem.id = judge_submission.problem_id) WHERE (judge_problem.is_public AND
WHERE (judge_problem.is_public = True AND judge_problem.is_organization_private = False AND judge_submission.points IS NOT NULL AND judge_submission.user_id = %s) NOT judge_problem.is_organization_private AND
judge_submission.points IS NOT NULL AND
judge_submission.user_id = %s)
GROUP BY judge_problem.id GROUP BY judge_problem.id
HAVING MAX(judge_submission.points) > 0.0 HAVING MAX(judge_submission.points) > 0.0
) AS max_points_table ) AS max_points_table
ON (judge_submission.problem_id = max_points_table.problem_id AND judge_submission.points = max_points_table.max_points AND judge_submission.user_id = %s) INNER JOIN judge_submission ON (
judge_submission.problem_id = max_points_table.problem_id AND
judge_submission.points = max_points_table.max_points AND
judge_submission.user_id = %s
)
INNER JOIN judge_language ON (judge_submission.language_id = judge_language.id)
GROUP BY max_points_table.problem_id GROUP BY max_points_table.problem_id
ORDER BY max_points DESC, judge_submission.date DESC ORDER BY max_points DESC, judge_submission.date DESC
LIMIT %s LIMIT %s OFFSET %s
OFFSET %s
) AS submission
JOIN judge_language
ON submission.language_id = judge_language.id
ORDER BY submission.max_points DESC, submission.sub_date DESC;
""", """,
(user.id, user.id, end - start + 1, start), (user.id, user.id, end - start + 1, start),
) )