使用多对多关系SQLAlchemy删除数百万行



我有两个表,它们具有以下多对多关系

def TableOne(db.Model):
__tablename__ = "table_one"
id = db.Column(db.Integer, primary_key=True)
table_twos = db.relationship(
"TableTwo", secondary=relationship_table, lazy="subquery"
)
# Some other attributes
def TableTwo(db.Model):
__tablename__ = "table_two"
id = db.Column(db.Integer, primary_key=True)
relationship_table = db.Table(
"relationship_table",
db.Column("table_one_id", db.Integer, db.ForeignKey("table_one.id"), primary_key=True),
db.Column(
"table_two_id",
db.Integer,
db.ForeignKey("table_two.id"),
primary_key=True,
),
)

通常情况下,我一直在做小项目,我可以删除所有的关系,如下

tables = db.session.query(TableOne).all()
for t in tables:
t.table_twos = []
db.session.flush()
db.session.commit()
table_twos = db.session.query(TableTwo).all()
for t in table_twos:
db.session.delete(t)
db.session.flush()
db.session.commit()

然而,由于我正在处理数百万行,我不能将它们全部加载到内存中。如果我试图删除所有的TableTwo行,它会给我一个关于外键的错误。

如何一次性删除所有关系,然后一次性删除TableTwo行?

谢谢

如果要删除表中的所有行,使用TRUNCATE要快得多,它只是将表文件丢弃在磁盘上,而不是逐个删除每一行。它还会回收磁盘空间,不像DELETE只会在表文件中创建空闲空间。

如果有外键:

可以TRUNCATE引用表(TableTwo)。

但是不能截断引用的表,因为这会破坏外键引用。但是如果要删除引用表和被引用表中的所有行,只需截断它们:

TRUNCATE table1, table2;

如果引用表和被引用表在同一个truncate命令中列出,它将工作。不要使用两个独立的TRUNCATE命令,否则postgres将拒绝打破您的外键(它应该!)。

注意,如果您希望删除table1中的行也删除table2中的引用行,您必须将外键设置为&;ON delete cascade &;。然后,您可以在table1上使用DELETE,但是要删除所有行,TRUNCATE要快得多。