(转发)[Flask]sqlalchemy批量插入数据(性能对比)
今天接到一个用户的需求,说排班管理那里一次性排一年以上的班次会报错,而且时间太久,需要做优化,经测试,报错原因是前端限制了后端返回数据的时间,导致直接报服务器错误。让前端将限制调制10分钟,一次请求两个月的排班,发现耗时为29秒,测试一年的排班,时间达到了可怕的174秒,搁谁身上都会崩溃,也不知道当时的开发和测试是怎么过的。既来之则安之,先进性优化吧。
原代码实现类似于方式一,插入数据库很快,但是会卡在commit那里,经修改后采用了方式四的方式,经过测试一年的数据量也就1秒左右,效率一下提升几百倍。
文章原博客地址已经无法访问了,这篇文章是从http://www.manongjc.com/detail/8-fjqznbdwcmthgru.html转发的,防止以后自己用到了再去网上寻找,特此搬过来了。
方式一
first_time = datetime.utcnow()
for i in range(10000):
user = User(username=username + str(i), password=password)
db.session.add(user)
db.session.commit()
second_time = datetime.utcnow()
print((second_time - first_time).total_seconds())
# 38.14347s
方式二
second_time = datetime.utcnow()
db.session.bulk_save_objects(
[
User(username=username + str(i), password=password)
for i in range(10000)
]
)
db.session.commit()
third_time = datetime.utcnow()
print((third_time - second_time).total_seconds())
# 2.121589s
方式三
third_time = datetime.utcnow()
db.session.bulk_insert_mappings(
User,
[
dict(username="NAME INSERT " + str(i), password=password)
for i in range(10000)
]
)
db.session.commit()
fourth_time = datetime.utcnow()
print((fourth_time - third_time).total_seconds())
# 1.13548s
方式四
fourth_time = datetime.utcnow()
db.session.execute(
User.__table__.insert(),
[{"username": 'Execute NAME ' + str(i), "password": password} for i in range(10000)]
)
db.session.commit()
five_time = datetime.utcnow()
print((five_time - fourth_time).total_seconds())
# 0.888822s