Как пропустить накладные расходы ORM в результате? - PullRequest
0 голосов
/ 16 февраля 2019

У меня есть модель sqlalchemy ORM, мне нужно создать запрос (который легче создать с помощью классов ORM), но это занимает огромное количество времени.Когда я выполняю тот же запрос непосредственно к базе данных, что и SQL, он выполняется довольно быстро.

Использование функции профиля, представленной в SQLAlchemy doc 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, но я получаю что-то вроде "Bundle is notableable" (конечно, из-заприсоединиться)

1 Ответ

0 голосов
/ 16 февраля 2019

Если вы хотите продолжить использовать 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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...