如何提高 django mysql 复制性能?

How can I improve django mysql copy performance?

我有一个定义了模型 (Person) 的 django 应用程序,我还有一些没有任何模型的数据库(其中有一个 table Appointment)已定义(并不意味着连接到 django 应用程序)。

我需要将一些数据从 Appointment table 移到 Person 以便人们 table 需要反映约会 table 的所有信息].之所以这样,是因为有多个独立的数据库,例如 Appointment,需要复制到 Person table(所以我不想对其设置方式进行任何架构更改)。

这是我现在所做的:

res = sourcedb.fetchall() # from Appointment Table
for myrecord in res:
    try:
        existingrecord = Person.objects.filter(vendorid = myrecord[12], office = myoffice)[0]
    except:
        existingrecord = Person(vendorid = myrecord[12], office = myoffice)

    existingrecord.firstname    = myrecord[0]
    existingrecord.midname      = myrecord[1]
    existingrecord.lastname     = myrecord[2]
    existingrecord.address1     = myrecord[3]
    existingrecord.address2     = myrecord[4]
    existingrecord.save()

问题是这太慢了(20K 条记录大约需要 8 分钟)。我该怎么做才能加快速度?

我考虑过以下方法:

1. bulk_create: 不能用这个,因为我有时要更新。

2。全部删除然后bulk_create Person模型对其他东西有依赖性,所以无法删除Person模型中的记录。

3。 INSERT ... ON DUPLICATE KEY UPDATE: 无法执行此操作,因为 Person table 的 PK 不同于 Appointment table PK(主键)。约会 PK 被复制到 Person table。如果有一种方法可以检查两个重复的键,我认为这种方法会起作用。

一些想法:

  • 编辑:请参阅 Trewq 对此的评论并首先在您的 table 上创建索引……
  • 使用 with transaction.atomic(): 将其全部包装在一个事务中,因为默认情况下 Django 会在每次 save() 调用时创建一个新事务,这可能会变得非常昂贵。对于 20K 条记录,一个巨大的交易也可能是个问题,因此您可能必须编写一些代码将您的交易分成多个批次。试用并测量!
  • 如果 RAM 不是问题(不应该有 20k 条记录),请先从约会 table 获取所有数据,然后使用单个 SELECT 查询获取所有现有的 Person 对象每条记录一个
  • 使用 bulk_create 即使其中一些是更新。这仍然会为您的更新发出 UPDATE 查询,但会将所有 INSERT 查询减少到 one/a 几个,这仍然是一个改进。您可以通过以下事实来区分插入和更新:插入在调用 save() 之前不会设置主键并将插入保存到 Python 列表中以供稍后 bulk_create 而不是直接保存它们
  • 作为最后的手段:编写原始 SQL 以利用 MySQLs INSERT … ON DUPLICATE KEY UPDATE 语法。您不需要为此使用相同的主键,UNIQUE 键就足够了。键可以跨越多列,参见 Django 的 Meta.unique_together 模型选项。