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

Django上传大型数据集时高效检查数据是否存在的方法

高效导入Excel数据到Django Student模型的优化方案

问题背景

需要将包含17000行数据的Excel表格导入Django的Student模型,但当前实现每次循环都会发起数据库查询,导致导入效率极低,现需高效检查数据是否已存在的优化方案。

现有代码

models.py

# no fields value are unique here,
class Student(models.Model):
    name=models.CharField(max_length=100)
    address=models.CharField(max_length=100)
    age=models.CharField(max_length=100)
    rollno=models.CharField(max_length=100)

views.py

def upload_script(request):
    wb = openpyxl.load_workbook(excel_file)
    worksheet = wb["All DMAs"]
    
    for row in worksheet.iter_rows():
        datacollection=row[0:9]
        name=datacollection[0]
        address=datacollection[1]
        rollno=datacollection[2]
        age=datacollection[3]
   
      # everytime this call the database which load more time
       if(Student.objects.filter(name=name,address=address,rollno=rollno,age=age).first()):
          continue

       student_obj=Student(
             name=name,
             address=address,
             rollno=rollno,
             age=age
          )
      student_list.append(student_obj)
      if len(student_list)>1000:
         Student.objects.bulk_create(student_list)
         student_list=[]
    Student.objects.bulk_create(student_list)

优化方案

1. 添加联合唯一约束(可选但推荐)

在Student模型中添加联合唯一约束,既保证数据库层面的数据唯一性,又能加速后续批量查询:

class Student(models.Model):
    name=models.CharField(max_length=100)
    address=models.CharField(max_length=100)
    age=models.CharField(max_length=100)
    rollno=models.CharField(max_length=100)

    class Meta:
        # 四个字段组合唯一,同时生成联合索引加速查询
        unique_together = ('name', 'address', 'rollno', 'age')

执行迁移更新数据库:

python manage.py makemigrations
python manage.py migrate

2. 批量预查询现有数据,内存中比对

一次性查询所有已存在的学生标识(四个字段的组合)存入内存集合,循环导入时直接在内存中判断,避免频繁数据库查询:

优化后的views.py

def upload_script(request):
    wb = openpyxl.load_workbook(excel_file)
    worksheet = wb["All DMAs"]
    
    # 一次性获取所有已存在的学生组合,存入集合(O(1)时间复杂度查找)
    existing_student_keys = set(
        Student.objects.values_list('name', 'address', 'rollno', 'age')
    )
    
    student_list = []
    # 直接读取单元格值,跳过处理Cell对象的开销
    for row in worksheet.iter_rows(min_row=2, values_only=True):  # min_row=2跳过表头,按需调整
        name = row[0]
        address = row[1]
        rollno = row[2]
        age = row[3]
        
        # 内存快速判断,无需触发数据库查询
        if (name, address, rollno, age) in existing_student_keys:
            continue
        
        student_obj = Student(
            name=name,
            address=address,
            rollno=rollno,
            age=age
        )
        student_list.append(student_obj)
        
        # 每1000条批量插入,减少数据库交互次数
        if len(student_list) >= 1000:
            Student.objects.bulk_create(student_list)
            student_list = []
    # 处理剩余未提交的数据
    if student_list:
        Student.objects.bulk_create(student_list)

优化说明

  • 批量预查询:将原有的O(n)次数据库查询缩减为1次,集合查找的时间复杂度为O(1),大幅降低数据库交互开销。
  • Excel读取优化:values_only=True直接返回单元格数值,避免处理Cell对象带来的错误和额外操作。
  • 联合索引加速:联合唯一约束自动生成的索引,让预查询的values_list执行效率更高。

内容的提问来源于stack exchange,提问作者BHUWAN PANDEY

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 21:06:21