如何跳过ORM开销结果?

时间:2019-02-16 15:49:18

标签: python sqlalchemy

我有一个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,但是却收到类似“无法选择捆绑”的信息(肯定是由于连接)

1 个答案:

答案 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'