首页 > 解决方案 > Flask-SqlAlchemy 加载大量数据后插入速度极慢

问题描述

我有一张大约有 20 万条记录的表。我正在尝试使用 Flask-SqlAlchemy 批量插入大约 20 条记录。通常大约需要 20 毫秒,但是当我在插入之前从表中加载所有记录时,大约需要 1000 毫秒(慢 50 倍)。为什么?

from models import LocationMap, db
import random
import time
# the last line 'db.session.commit()' will be extremely slow when I uncomment this line.
#known_locations = LocationMap.query.all()
for i in range(10):
    loc = LocationMap()
    loc.longitude = 0 #location_batch[i + j][0]
    loc.latitude = random.random() #location_batch[i + j][1]
    loc.country = 'test'
    loc.province = 'test2'
    loc.city = 'test3'
    loc.district = 'test4'
    loc.township = 'test5'
    db.session.add(loc)

st = time.time()
db.session.commit()
print(time.time() - st)

标签: pythonperformanceflasksqlalchemy

解决方案


我认为这与实例、引用、身份映射等的跟踪/状态有关。换句话说 - 我认为原因主要是相似ORM的工作方式(sqlalchemy不是很小ORM)。这就是为什么这些类型的工具在处理大型数据集时性能较差的原因。但是它们具有非常强大的功能。

我将尝试用一个例子来解释:

locations = LocationMap.query.all()
locations[0].country = 'new value1'
locations[1].country = 'new value2'
for i in range(10):
    # ... db.session.add(loc)

db.session.commit()

会发生什么?是的 - 我们将不仅有插入。我们还将有 2 个更新(new value1, new value2)。因为Session具有对所有对象的引用。现在让我们尝试从 a 中删除选定的实例Session

locations = LocationMap.query.all()
db.session.expunge_all()
# your code here... for i in range(10): 

您会看到该操作需要大约 20 毫秒(正常时间)。您还可以从 a 中删除特定对象Session

locations = LocationMap.query.all()
for l in locations:
    # if we don't need reference anymore
    db.session.expunge(l)

否则,ORM如果性能对您至关重要,您可以拒绝。


推荐阅读