sqlalchemy延迟加载

概述

参考:https://blog.youkuaiyun.com/u012324798/article/details/103940527
sqlalchemy对字表加载有好几种方法,主要有两类:立即加载和延迟加载。
关系加载的主要形式是:

lazyload()

延迟加载 -可通过 lazy=‘select’ 或 lazyload() 选项实现。
这是默认的加载方式,当需要加载字表的时候再进行数据库访问,所以一对多的时候可能会出现多次访问数据库的问题。

joinedload()

采用左加载left join。(如果要改为inner join ,则加参数joinedload(User.addresses,innerjoin=True)
联合加载 -可通过 lazy=‘joined’ 或 joinedload() 选项,此加载形式将联接应用于给定的select语句,以便在同一结果集中加载相关行。联合预加载在 加入的热切装载 .
注意:只能加载一个数据

subqueryload()

子查询加载 -可通过 lazy=‘subquery’ 或 subqueryload() 选项,此加载形式发出第二个select语句,该语句重新声明嵌入在子查询中的原始查询,然后将该子查询联接到要加载的相关表,以一次加载相关集合/标量引用的所有成员。子查询预加载的详细信息位于 子查询预加载 .
多方关联数据集合很大时使用subqueryload,一次查询数量不超过500条则使用selectinload()更合适。
总共2条SQL语句,第1条查询user,第2条填充user.addresses,使用INNER JOIN,不改变一方查询结果,且子查询的字段仅为一方表主键
缺点:如果查询中使用了first、limit、offset,则必须同时使用order_by,否则可能产生错误结果

selectinload()

加载时选择 -可通过 lazy=‘selectin’ 或 selectinload() 选项,此加载形式发出第二个(或更多)select语句,将父对象的主键标识符组装到in子句中,以便相关集合/标量引用的所有成员都按主键一次加载。加载中的选择详细信息位于 加载时选择 .
注意:可以加载多个数据
当要同时加载多个不同的多方关联表数据(及需要join多个表)时使用selectinload
总共1+(N / 500)条SQL语句,第1条查询user,第2条(及以后)填充user.addresses,不会产生笛卡尔积问题,不会多次join,无需order_by,性能高
缺点:一个SQL语句一次只能获取多方关联数据集合的500条数据,集合数据量超过500时,将每500个发出一个SQL
缺点:对于复合主键,selectin加载不是平台无关的,已知支持的DBAPI为PostgreSQL, MySQL, SQLite,对于不支持的DBAPI将抛异常

raiseload()

如果进行了额外的加载查询,则报错。
加荷 -可通过 lazy=‘raise’ , lazy=‘raise_on_sql’ ,或者 raiseload() 选项,此形式的加载在通常发生延迟加载的同时触发,除非它引发ORM异常以防止应用程序进行不需要的延迟加载。提升负载的介绍在 使用raiseload防止不需要的懒惰负载 .

noload()

不进行加载,值直接赋值为空。
无负载 -可通过 lazy=‘noload’ ,或者 noload() 选项;此加载样式将属性转换为永远不会加载或具有任何加载效果的空属性。”“noload”是一个非常罕见的加载程序选项。

结论

【结论】多方关联数据集合较小时使用joinedload,其他情况能用selectinload就用selectinload,用不了就改用subqueryload

### SQLAlchemy 使用指南 SQLAlchemy 是 Python 生态中最强大的数据库操作工具之一,支持从简单到复杂的各种数据处理需求[^1]。以下是关于如何使用 SQLAlchemy 进行常见任务以及解决问题的详细说明。 #### 创建 ORM 基类 为了定义模型并与数据库交互,通常会先创建一个基于 `declarative_base` 的基类。此过程可以通过以下方式实现: ```python from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base DB_URI = 'sqlite:///example.db' # 替换为实际使用的 URI engine = create_engine(DB_URI, echo=True) # 设置 echo 参数可查看 SQL 日志 Base = declarative_base(bind=engine) ``` 这段代码展示了如何通过指定数据库连接字符串来初始化引擎,并绑定至声明式基础类[^3]。 #### 定义模型 在 SQLAlchemy 中,可以利用继承自 `Base` 类的对象表示表结构。例如,下面是一个简单的用户表定义示例: ```python from sqlalchemy import Column, Integer, String class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50)) email = Column(String(100), unique=True) def __repr__(self): return f"<User(name={self.name}, email={self.email})>" ``` 这里我们定义了一个名为 `users` 的表及其字段属性[^3]。 #### 关系映射 (Relationship Mapping) 当涉及到多个表格之间的联系时,SQLAlchemy 提供了灵活的关系机制。比如设置一对一、一对多或者多对多关系等。以一对多为例: ```python from sqlalchemy.orm import relationship class Address(Base): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey('users.id')) address = Column(String(200)) user = relationship("User", back_populates="addresses") User.addresses = relationship( "Address", order_by=Address.id, back_populates="user" ) ``` 上述片段建立了两个实体间的一对多关联[^4]。 #### 查询优化技巧 对于性能敏感的应用场景来说,延迟加载(lazy loading) 和提前获取(eager loading) 可能会影响程序表现。如果需要控制这些行为,则可通过调整策略选项完成定制化配置: ```python session.query(User).options(defer("email")) ``` 该语句表明,在读取 `User` 实体时不立即载入其邮箱地址部分的信息[^2]。 --- ### 常见问题解决方案 1. **无法找到模块错误** 如果遇到类似于 ModuleNotFoundError 错误提示找不到某些组件,请确认已安装最新版本库文件并通过 pip freeze 查看依赖列表验证环境一致性。 2. **事务提交失败** 当尝试保存更改却收到异常反馈时,可能是因为未显式调用 commit() 函数结束当前事务周期所致;记得每次修改完成后都要执行 session.commit() 动作才能持久化改动成果。 3. **跨平台兼容性难题** 不同操作系统下路径分隔符差异可能导致脚本移植困难。建议统一采用 os.path.join 方法构建绝对路径表达式代替硬编码斜杠字符形式书写相对位置描述词组串列组合而成的结果作为最终目标定位依据。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值