我有一个ORM sqlalchemy模型,我需要构造一个查询(使用ORM类构造起来更容易),但是要花费大量时间。当我直接对数据库执行与SQL相同的查询时,它非常快。
使用SQLAlchemy文档https://docs.sqlalchemy.org/en/latest/faq/performance.html中提供的配置文件功能,我发现确实是ORM增加了巨大的开销。
但是,查询结果用在几段代码中,所以到处更改都会很麻烦。
查询如下:
q = ( session.query(T1, T2)
.select_from(sub_query)
.join(T1, sub_query.c.id == T1.id)
.join(T2, sub_query.c.id==T2.id)
.filter(T1.user == 1)
.order_by(T1.group, T1.position)
)
行未修改,仅使用T1和T2属性读取它们。 (我的意思是,我不需要获取T1和T2对象,就像原始对象具有与T1和T2的列名匹配的属性一样)
有没有一种方法可以加快速度(消除ORM开销),以便我可以使用相同的语法访问它们,例如
for t1, t2 in q.all():
print(t1.x, t2.x)
?
我已经尝试过sqlalchemy.orm.Bundle
,但是却收到类似“无法选择捆绑”的信息(肯定是由于连接)
答案 0 :(得分:2)
如果您希望继续使用SQLAlchemy,但在这种特殊情况下避免了ORM的开销,则可以尝试使用Bundle
:
from sqlalchemy import inspect
from sqlalchemy.orm import Bundle
def to_bundle(cls, label=None):
return Bundle(label or cls.__name__,
*[c.class_attribute for c in inspect(cls).column_attrs])
q = ( session.query(to_bundle(T1), to_bundle(T2))
.select_from(sub_query)
.join(T1, sub_query.c.id == T1.id)
.join(T2, sub_query.c.id==T2.id)
.filter(T1.user == 1)
.order_by(T1.group, T1.position)
)
您不应将捆绑软件传递给Query.join()
,而应传递给映射的类。捆绑软件将从连接结果中提取列。如果您确实通过了捆绑软件,则会收到错误消息:
AttributeError: 'Bundle' object has no attribute 'selectable'