SQLAlchemy查询底层与延迟问题:filter快jsonify慢的原因
SQLAlchemy查询性能疑问解答
用户问题
伪代码
from sqlalchemy.orm import query query = MyClass.query if arg1: query = query.filter(MyClass.f1 == arg1) if arg2: query = query.filter(MyClass.f2 == arg2) if arg3: query = query.filter(MyClass.f3 == arg3) res = jsonify(requests=[r.to_dict() for r in query]) return res
性能现象与疑问
query.filter执行极快(约0.0001s),而jsonify(requests=[r.to_dict() for r in query])是耗时瓶颈(约0.3s)- 日志显示实际SQL操作在
query.filter之后才执行,对此感到困惑
日志片段
f1 time 0.0002 f2 time 0.0001 2023-05-04 09:37:09,667 INFO sqlalchemy.engine.base.Engine SELECT 1 INFO:sqlalchemy.engine.base.Engine:SELECT 1 2023-05-04 09:37:09,667 INFO sqlalchemy.engine.base.Engine () INFO:sqlalchemy.engine.base.Engine:() 2023-05-04 09:37:09,668 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) INFO:sqlalchemy.engine.base.Engine:BEGIN (implicit) 2023-05-04 09:37:09,669 INFO sqlalchemy.engine.base.Engine SELECT ... ... ... jsonify time 0.31 ...
问题解答
1. 为什么query.filter执行极快,SQL操作延迟到遍历阶段?
SQLAlchemy的ORM查询采用**延迟加载(懒执行)**机制:
- 调用
query.filter()时,并没有实际执行SQL语句,只是在构建一个查询对象,把过滤条件、表结构等信息封装起来,本质是组装查询逻辑,没有和数据库产生实际交互,所以耗时极短。 - 只有当你实际需要获取数据的时候(比如遍历query对象、调用
all()/first()等方法),SQLAlchemy才会把之前组装好的查询转换成SQL语句,发送给数据库执行,再把结果映射成ORM对象。这就是日志里SQL操作在遍历阶段才出现的原因。
2. 为什么jsonify(...)是耗时瓶颈?
这一行的耗时包含三个核心环节:
- 数据库查询执行:数据库执行SELECT语句并返回结果集,数据量越大这部分耗时越明显。
- ORM对象映射:数据库返回的原始数据会被转换成MyClass的实例对象,涉及字段映射、对象初始化等操作,会占用一定时间。
- 对象转字典+JSON序列化:
r.to_dict()需要把每个ORM对象的属性转换成字典结构,之后jsonify还要把字典列表序列化成JSON字符串,这两步对于大量数据来说,序列化的开销会非常突出,是0.3s耗时的主要来源之一。
内容的提问来源于stack exchange,提问作者LookIntoEast
相关产品推荐
相关产品推荐

