Flask-SqlAlchemy 加载大量数据后插入速度极慢

Flask-SqlAlchemy insert extremely slow after load large amount of data

我有一个 table 大约有 20 万条记录。我正在尝试使用 Flask-SqlAlchemy 批量插入大约 20 条记录。通常需要大约 20 毫秒,但是当我在插入之前从 table 加载所有记录时,大约需要 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)

我认为这与跟踪/实例状态、引用、身份映射等有关。换句话说 - 我认为原因主要是 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 value1new value2)。因为 Session 具有对所有对象的引用。现在让我们尝试从 Session:

中删除选定的实例
locations = LocationMap.query.all()
db.session.expunge_all()
# your code here... for i in range(10): 

您会看到操作需要大约 20 毫秒(正常时间)。您还可以从 Session:

中删除特定对象
locations = LocationMap.query.all()
for l in locations:
    # if we don't need reference anymore
    db.session.expunge(l)

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