使用Flask-SQLAlchemy批量插入

时间:2015-05-19 04:43:31

标签: python flask sqlalchemy flask-sqlalchemy

我使用Flask-SQLAlchemy做了一个相当大的60k行的批量插入。我在这张桌子上也有多对多的关系,因此我无法使用db.engine.execute。在插入之前,我需要在数据库中找到类似的项目,如果找到重复的项目,则将插入更改为更新。

我可以事先检查,然后通过db.engine.execute进行批量插入,但我需要在插入时插入行的主键。

目前,我正在每个插页上执行db.session.add()db.session.commit(),而我每秒只能获得3-4次插入。

我运行了一个分析器来查看瓶颈在哪里,似乎db.session.commit()占用了60%的时间。

是否有某种方法可以让我更快地完成此操作,可能是通过对提交进行分组,但这会给我主键回复?

这就是我的模型:

class Item(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(1024), nullable=True)
    created = db.Column(db.DateTime())
    tags_relationship = db.relationship('Tag', secondary=tags, backref=db.backref('items', lazy='dynamic'))
    tags = association_proxy('tags_relationship', 'text')

class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(255))

我的插入操作是这样运行的:

for item in items:
    if duplicate:
        update_existing_item
    else:
        x = Item()
        x.title = "string"
        x.created = datetime.datetime.utcnow()
        for tag in tags:
            if not tag_already_exists:
                y = Tag()
                y.text = "tagtext"
                x.tags_relationship.append(y)
                db.session.add(y)
                db.session.commit()
            else:
                x.tags_relationship.append(existing_tag)
    db.session.add(x)
    db.session.commit()

2 个答案:

答案 0 :(得分:2)

也许您应该尝试db.session.flush()将数据发送到服务器,这意味着将生成任何主键。最后,您可以db.session.commit()实际提交交易。

答案 1 :(得分:2)

我使用以下代码快速将pandas DataFrame的内容读入SQLite。请注意,它绕过了SQLAlchemy的ORM功能。此上下文中的myClass是db.Model派生类,其具有分配给它的表名。正如代码片段提到的那样,我改编了

l = df.to_dict('records')
# bulk save the dictionaries, circumventing the slow ORM interface
# c.f. https://gist.github.com/shrayasr/5df96d5bc287f3a2faa4
connection.engine.execute(
    myClass.__table__.insert(),
    l
)