Django 更新或创建的性能优化

yge*_*her 6 django optimization

在 Django 项目中,我每天从外部 API 刷新数万行数据。问题是,由于我不知道数据是新的还是只是更新,我无法进行bulk_create操作。

注意:有些行,或者很多行,实际上并没有每天更改,但我不知道哪些或多少行提前。

所以现在我这样做:

for row in csv_data:
    try:
        MyModel.objects.update_or_create(id=row['id'], defaults={'field1': row['value1']....})
    except:
        print 'error!'
Run Code Online (Sandbox Code Playgroud)

它需要......永远!每秒一两行,最大速度,有时每行几秒钟。我刷新的每个模型都有一个或多个其他模型通过外键连接到它,所以我不能只是将它们全部删除并每天重新插入。我无法解决这个问题——我怎样才能显着减少数据库操作的数量,以便刷新不会花费数小时和数小时。

谢谢你的帮助。

Yar*_*atz 6

问题是您正在对从 api 获取的每个数据行执行数据库操作。您可以通过了解哪些行是新行(并对所有新行进行批量插入)、哪些行实际需要更新以及哪些行没有更改来避免这样做。详细说明:

  1. 从数据库中获取所有相关行(意味着所有可能更新的行)
old_data = MyModel.objects.all() # if possible than do MyModel.objects.filter(...)
Run Code Online (Sandbox Code Playgroud)
  1. 获取您需要插入或更新的所有 api 数据
api_data = [...]
Run Code Online (Sandbox Code Playgroud)
  1. 对于每一行数据了解它是否是新的并将其放入数组中,或者确定该行是否需要更新数据库
    for row in api_data:
        if is_new_row(row, old_data):
            new_rows_array.append(row)
        else:
            if is_data_modified(row, old_data):
                ...
                # do the update
            else:
                continue
     MyModel.objects.bulk_create(new_rows_array)
Run Code Online (Sandbox Code Playgroud)

is_new_row - 将了解该行是否为新行并将其添加到将被批量创建的数组中

is_data_modified - 将在旧数据中查找该行并了解该行的数据是否已更改,并且仅在其更改时才更新

  • 这不会导致竞争条件吗?我的意思是:您从数据库中获取所有现有行,并检查从 api 接收的数据是否已经存在。如果同时另一个用户删除或插入新条目怎么办?如果使用 mysql/mariadb,那么使用原始 sql 查询(如“INSERT ON DUPLICATE KEY UPDATE”)不是更好的解决方案吗? (2认同)