我有一个 django 应用程序,它定义了一个模型(Person
),并且我还有一些没有任何模型的数据库(其中有一个表Appointment
)定义(不意味着连接到 django 应用程序)。
我需要将一些数据从Appointment
表移至Person
,以便People 表需要的所有信息都能镜像Appointment 表。之所以如此,是因为有多个独立的数据库(例如 Appointment)需要复制到 Person 表(因此我不想对其设置方式进行任何架构更改)。
这是我现在所做的:
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。删除所有,然后批量创建 Person 模型对其他事物有依赖性,因此我无法删除 Person 模型中的记录。
<强>3。 INSERT ... ON DUPLICATE KEY UPDATE: 无法执行此操作,因为 Person 表的 PK 与 Appointment 表 PK(主键)不同。约会 PK 被复制到人员表中。如果有一种方法可以检查两个重复的键,我认为这种方法会起作用。
最佳答案
一些想法:
- 编辑:请参阅 Trewq 对此的评论,并首先在您的表上创建索引...
- 使用
with transaction.atomic():
将其全部封装在一个事务中,因为默认情况下,Django 会在每次调用save()
时创建一个新事务,这可能会变得非常困难。昂贵的。对于 20K 条记录,一笔巨大的交易也可能是一个问题,因此您可能需要编写一些代码来将交易拆分为多个批处理。尝试并测量! - 如果 RAM 不是问题(不应包含 20k 条记录),请首先从约会表中获取所有数据,然后使用单个
SELECT
查询而不是每个人一个查询来获取所有现有的 Person 对象记录 - 即使其中一些是更新,也请使用
bulk_create
。这仍会针对您的更新发出UPDATE
查询,但会将所有INSERT
查询减少到一个/几个,这仍然是一项改进。您可以区分插入和更新,因为插入在调用save()
之前不会设置主键,并将插入保存到 Python 列表中以供以后使用bulk_create
而不是直接保存它们 - 作为最后的手段:编写原始 SQL 以利用 MySQL 的
INSERT … ON DUPLICATE KEY UPDATE
语法。为此,您不需要相同的主键,UNIQUE
键就足够了。键可以跨越多个列,请参阅 Django 的Meta.unique_together
模型选项。
关于python - 如何提高 django mysql 复制性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28547381/