[英]How to do a paged query with empty collections in SQLAlchemy?
我試圖找到一種內存有效的方法來執行分頁查詢以測試一個空集合,但是似乎無法弄清楚如何在大型數據庫上有效地進行處理。 表布局使用帶有雙向后向引用的關聯對象。 它與文檔非常相似。
class Association(Base):
__tablename__ = 'Association'
assoc_id = Column(Integer, primary_key=True, nullable=False, unique=True)
member_id = Column(Integer, ForeignKey('Member.id'))
chunk_id = Column(Integer, ForeignKey('Chunk.id'))
extra = Column(Text)
chunk = relationship("Chunk", backref=backref("assoc", lazy="dynamic"))
class Member(Base):
__tablename__ = 'Member'
id = Column(Integer, primary_key=True, nullable=False, unique=True)
assocs = relationship("Association", backref="member", cascade="all, delete", lazy="dynamic")
class Chunk(Base):
__tablename__ = 'Chunk'
id = Column(Integer, primary_key=True, nullable=False, unique=True)
name = Column(Text, unique=True)
如果成員被刪除,它將級聯並刪除成員的關聯。 但是,塊對象將在數據庫中孤立。 要刪除孤立的塊,我可以使用如下查詢來測試空集合:
session.query(Chunk).filter(~Chunk.assoc.any())
然后使用以下命令刪除這些塊:
query.delete(synchronize_session=False)
但是,如果關聯表和塊表很大,則查詢或子查詢似乎會加載所有內容和內存飛速增長。
我見過使用分頁查詢來限制標准查詢的內存使用量的概念, 在這里 :
def page_query(q, count=1000):
offset = 0
while True:
r = False
for elem in q.limit(count).offset(offset):
r = True
yield elem
offset += count
if not r:
break
for chunk in page_query(Session.query(Chunk)):
print chunk.name
但是,這似乎不適用於空集合查詢,因為內存使用率仍然很高。 有沒有辦法對這樣的空集合進行分頁查詢?
我發現這里缺少幾件事。 對空塊的查詢似乎幾乎可以。 我看到的內存使用高峰是在刪除實際成員本身時,在代碼中的前幾行從查詢中獲得的。
member = session.query(Member).filter(Member.name == membername).one()
session.delete(member)
根據文檔,會話(默認情況下)只能刪除加載到會話/內存中的對象。 刪除成員后,它將加載其所有關聯,以便按照級聯規則刪除它們。 需要發生的是,必須通過使用被動刪除來繞過關聯加載。
我補充說:
passive_deletes=True
會員類別的關聯關系,以及:
ondelete='CASCADE'
到Association類的member_id外鍵。 我正在使用SQLite3,並根據文檔在引擎連接事件中添加了外鍵支持。
關於孤立塊,而不是使用query.delete方法批量刪除塊。 我使用了一個不包含偏移量的頁面查詢,並在循環中從會話中刪除了大塊,如下所示。 到目前為止,我似乎沒有任何內存峰值:
def page_query(q):
while True:
r = False
for elem in q.limit(1000):
r = True
yield elem
if not r:
break
for chunk in page_query(query):
# Do something with the chunk if needed
session.delete(chunk)
session.commit()
長話短說,在刪除具有大量集合的父對象時使用passive_deletes = True似乎很有幫助。 頁面查詢似乎在這種情況下也能很好地工作,只是因為從會話內聯中刪除了大塊,所以我不得不取出偏移量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.