You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django测验系统大数量试题加载慢的优化方案咨询

Django在线测验系统试卷生成优化方案

1. 用批量数据库操作替代循环单条创建

问题核心大概率是循环创建QuestionDraft和AnswerDraft时,每一条记录都触发一次数据库插入查询,50题以上会产生成百上千次独立查询,累积耗时剧增。改用Django的bulk_create方法批量插入,能将多次查询合并为少数几次,大幅减少数据库交互开销。

示例代码:

# 1. 批量创建QuestionDraft
question_drafts = []
for question in selected_questions:
    q_draft = QuestionDraft(
        question_id=question.id,
        exam_id=current_exam.id,
        # 其他必填字段
    )
    question_drafts.append(q_draft)
QuestionDraft.objects.bulk_create(question_drafts)

# 2. 建立Question与QuestionDraft的映射,批量创建AnswerDraft
q_id_to_draft = {draft.question_id: draft for draft in question_drafts}
answer_drafts = []
for question in selected_questions:
    q_draft = q_id_to_draft[question.id]
    # 预取的answers直接遍历,无需再次查询
    for answer in question.answers.all():
        a_draft = AnswerDraft(
            question_draft=q_draft,
            content=answer.content,
            is_correct=answer.is_correct,
            # 其他需要复制的字段
        )
        answer_drafts.append(a_draft)
AnswerDraft.objects.bulk_create(answer_drafts)

2. 预关联数据,避免N+1查询

抽取试题时,提前用prefetch_related加载关联的Answer数据,避免循环中每次访问question.answers都触发新的数据库查询。

示例代码:

# 按科目抽取指定数量试题,同时预取关联的答案
selected_questions = Question.objects.filter(
    subject=target_subject
).prefetch_related('answers')[:required_num]

如果Question和Answer是反向关联,确保Answer模型中定义了related_name,或使用默认的question_set,prefetch_related同样适用。

3. 优化数据库索引

给常用过滤、关联的字段添加索引,提升查询和关联效率:

  • Question模型的subject字段(按科目过滤试题时用到)
  • QuestionDraft的question、exam外键字段
  • AnswerDraft的question_draft外键字段

示例模型修改:

class Question(models.Model):
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE, db_index=True)
    # 其他字段...

class QuestionDraft(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, db_index=True)
    exam = models.ForeignKey(Exam, on_delete=models.CASCADE, db_index=True)
    # 其他字段...

class AnswerDraft(models.Model):
    question_draft = models.ForeignKey(QuestionDraft, on_delete=models.CASCADE, db_index=True)
    # 其他字段...

4. 异步化试卷生成(可选)

如果试卷生成逻辑确实无法在短时间内完成,可以将生成任务异步化,避免前端页面长时间等待:

  • 使用Celery等异步任务框架,将试卷生成逻辑封装为异步任务
  • 用户触发生成操作后,前端立即返回响应,显示“生成中”状态
  • 任务完成后,通过websocket或轮询通知用户,跳转至已生成的试卷页面

5. 精简字段复制

检查AnswerDraft是否复制了Answer中所有字段,只保留学生作答和判分必需的字段,减少单条记录的数据量,降低插入和存储开销。比如无需复制的冗余描述字段,可以直接省略。

内容的提问来源于stack exchange,提问作者Giorgio Scarso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 19:45:39