如何跳过查询结果中的ORM开销?

2024-04-18 18:15:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个ORM sqlalchemy模型,我需要构造一个查询(用ORM类更容易构造),但是这需要大量的时间。当我直接向数据库执行与SQL相同的查询时,速度非常快。你知道吗

使用SQLAlchemy dochttps://docs.sqlalchemy.org/en/latest/faq/performance.html中提供的profile函数,我发现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,但是我得到了类似“Bundle是不可选择的”(当然是由于join)


Tags: 对象模型id数据库属性sqlalchemy时间orm
1条回答
网友
1楼 · 发布于 2024-04-18 18:15:57

如果您希望继续使用SQLAlchemy,但在这种特殊情况下避免了ORM的开销,那么可以使用^{},正如您所尝试的那样:

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(),而应传递映射类。bundle将从连接的结果中提取列。如果确实传递了包,则会出现错误:

AttributeError: 'Bundle' object has no attribute 'selectable'

相关问题 更多 >