簡體   English   中英

如何在SQLAlchemy中使用空集合進行分頁查詢?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM