Flask-SQLAlchemy 批量导入数据
约 71 个字 59 行代码 预计阅读时间 1 分钟
情境
现在需要导入一系列数据到主表和明细表。实体类定义如下:
实体类 |
---|
| class RouteEntity(db.Model):
__tablename__ = 'routes'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
update_time = db.Column(db.DateTime, default=datetime.now)
create_user = db.Column(db.Integer, db.ForeignKey('users.id'), default=0)
update_user = db.Column(db.Integer, default=0)
is_deleted = db.Column(db.Boolean, default=False)
# ...
@staticmethod
def from_dto(route_dto: Route, user_id: int):
route_points = [RoutePointEntity.from_dto(point, user_id) for point in route_dto.points]
return RouteEntity(
points=route_points,
create_user=user_id,
update_user=user_id
)
class RoutePointEntity(db.Model):
__tablename__ = 'route_points'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
create_time = db.Column(db.DateTime, default=datetime.now)
update_time = db.Column(db.DateTime, default=datetime.now)
create_user = db.Column(db.Integer, db.ForeignKey('users.id'), default=0)
update_user = db.Column(db.Integer, default=0)
is_deleted = db.Column(db.Boolean, default=False)
# ...
route_id = db.Column(db.Integer, db.ForeignKey('routes.id'), nullable=False)
# ...
parent_route = db.relationship('RouteEntity', backref=db.backref('points'))
|
常规做法
数据库操作 |
---|
| route_entity = RouteEntity.from_dto(route, user_id)
db.session.add(route_entity)
db.session.commit()
|
更快的做法
实体类 |
---|
| class RoutePointEntity(db.Model):
# ...
def to_bulk_insert_dict(self, route_id: int):
return {
'create_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'update_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'create_user': self.create_user,
'update_user': self.update_user,
'route_id': route_id,
# ...
}
|
数据库操作 |
---|
| route_entity = RouteEntity.from_dto(route)
route_entity_bare = RouteEntity(
create_user=user_id,
update_user=user_id
# 相比于 route_entity,这里面唯独不传 points
)
db.session.add(route_entity_bare)
db.session.flush() # 获取route_entity的ID,但不提交事务
for i in route_entity.points:
i.route_id = route_entity.id
db.session.execute(insert(RoutePointEntity), [i.to_bulk_insert_dict(route_entity_bare.id) for i in route_entity.points])
db.session.commit()
|
实测效果
使用 MySQL,当子表要插入 17849 条数据时,时间从 14 s 缩减到 5 s。