SQLAlchemy

SQLAlchemy 是一个 Python 的 ORM(对象关系映射)库,它提供了一种将关系型数据库中的表映射为 Python 对象的方式。在 SQLAlchemy 中,joinedload 和 subqueryload 是两种常用的加载策略,用于优化关联数据的加载方式。

joinedload

joinedload 是一种预先加载(eager loading)策略,它使用 JOIN 语句将相关的数据一次性加载到查询结果中。这意味着当你查询一个对象时,它的关联对象也会被同时加载,而不需要额外的查询。这可以减少数据库查询的次数,提高查询效率。

joinedload 的主要优势在于减少了数据库查询的次数,避免了 N+1 查询问题(即对于每个查询结果,都需要执行一次额外的查询来获取相关数据)。此外,使用 joinedload 还可以提高代码的可读性,因为你可以在一个查询中一次性获取所有需要的数据。

使用 joinedload 时,需要先定义好模型之间的关系,然后在查询中使用 joinedload 来指定要加载的关联表。例如,如果你有一个 User 模型和一个 Address 模型,并且它们之间存在一对多的关系,你可以使用 joinedload(User.addresses) 来在查询 User 对象时同时加载 Address 对象。

subqueryload

与 joinedload 不同,subqueryload 使用子查询的方式来加载关联数据。这意味着当你查询一个对象时,它会首先执行一个子查询来获取关联对象的 ID,然后再使用这些 ID 来加载关联对象。虽然 subqueryload 需要执行额外的查询,但它可以避免在某些情况下出现笛卡尔积的问题,从而在某些情况下可能比 joinedload 更高效。

subqueryload 适用于关联表数据量较大或关联关系较复杂的情况。在这种情况下,使用子查询可以避免一次性加载大量数据导致的性能问题。

需要注意的是,joinedload 和 subqueryload 都是预先加载策略,它们与 SQLAlchemy 的默认延迟加载(lazy loading)策略不同。延迟加载是在需要时才加载关联数据,这可能会导致额外的查询和性能问题。因此,在选择使用哪种加载策略时,需要根据实际情况进行权衡。

多对多

from sqlalchemy import Column, Integer, String, ForeignKey  
from sqlalchemy.orm import relationship  
from sqlalchemy.ext.declarative import declarative_base  
  
Base = declarative_base()  
  
class User(Base):  
    __tablename__ = 'users'  
  
    id = Column(Integer, primary_key=True)  
    name = Column(String)  
    # 其他字段...  
  
class Item(Base):  
    __tablename__ = 'items'  
  
    id = Column(Integer, primary_key=True)  
    description = Column(String)  
    # 其他字段...
	
from sqlalchemy.orm import relationship  
from sqlalchemy import Table, Column, Integer, ForeignKey  
  
# 定义关联表  
user_item_association_table = Table('user_items', Base.metadata,  
    Column('user_id', Integer, ForeignKey('users.id')),  
    Column('item_id', Integer, ForeignKey('items.id'))  
)


from sqlalchemy.orm import relationship  
  
class User(Base):  
    # ...其他字段和定义...  
    items = relationship("Item", secondary=user_item_association_table, back_populates="users")  
  
class Item(Base):  
    # ...其他字段和定义...  
    users = relationship("User", secondary=user_item_association_table, back_populates="items")
posted @ 2024-05-14 14:44  Tank-Li  阅读(76)  评论(0编辑  收藏  举报