SQLAlchemy ORM与Core API对比及会话管理
请对比SQLAlchemy中ORM(对象关系映射)和Core(核心SQL表达式)两种API的适用场景和性能差异。说明Session的生命周期管理原则,解释session.commit()、session.flush()和session.close()的区别。什么是N+1查询问题,如何在SQLAlchemy中通过joinedload/subqueryload/selectinload优化?
回答
苦行僧
ORM vs Core: | 特性 | ORM | Core | |------|-----|------| | 编程方式 | 面向对象 | SQL表达式 | | 性能 | 较低(有对象映射开销) | 高(直接操作行数据) | | 适合场景 | 业务逻辑复杂、需对象级联 | 批量操作、报表查询 | | 事务控制 | Session | Connection |
Session管理(原则:一次请求一个Session):
from sqlalchemy.orm import Session
with Session(engine) as session:
user = session.get(User, 1)
user.name = 'new_name'
session.commit() # 提交事务,自动flush
# 退出with自动close
flush():将变更发送到数据库(生成SQL),未commitcommit():flush + 提交事务close():归还连接到池,清除对象
N+1查询优化:
# N+1问题:查询用户后,遍历时每条触发一次address查询
users = session.query(User).all()
for user in users:
print(user.addresses) # N次查询
# 优化:联合加载
from sqlalchemy.orm import joinedload, selectinload
users = session.query(User).options(
selectinload(User.addresses) # 用IN查询(推荐)
# joinedload(User.addresses) # 用LEFT JOIN
).all()
selectinload是默认推荐方式,发一条WHERE id IN (...)查询。