отложенная загрузка столбца sqlalchemy — не кажется более эффективной

#performance #sqlalchemy #loading #deferred

#Производительность #sql — алхимия #Загрузка #отложенный

Вопрос:

Я пытался оптимизировать запрос, и, несмотря на все усилия, не похоже, что следующие два запроса имеют существенно различающуюся производительность. Возможно ли, что сложность объектов, отображаемых ORM, заменяет любые выгоды, достигнутые в DBAPI? Если да, есть ли решение?

 baseContactQuery = contact.query.options(Load(contact).load_only(contact.user_id, contact.organization_contact, contact.relationship_strength, contact.full_name, contact.first_name, contact.last_name)).
        options(selectinload(contact.organization_references).load_only(organization_contact_reference.contact_sharing_level)).
        options(selectinload(contact.jobs).load_only(job.is_primary, job.role).options(selectinload(job.tied_company).load_only(company.name), lazyload('*'))).
        options(selectinload(contact.emails).load_only(email.email, email.is_primary)).
        options(selectinload(contact.contact_user).load_only(user.id).selectinload(user.organization_references).load_only(organization_user_reference.default_contact_sharing_level))
 

против.

 baseContactQuery = contact.query.
    options(selectinload(contact.organization_references)).
    options(selectinload(contact.jobs)).
    options(selectinload(contact.emails)).
    options(selectinload(contact.contact_user).selectinload(user.organization_references)) 
 

Комментарии:

1. Если они превратятся в SQL, давайте посмотрим SQL.

2. Итак, я просто сравнил два, и, похоже, он замедляется после добавления множества фильтров (не показано в baseContactQuery). Вот SQL, который генерируется со всеми включенными фильтрами. docs.google.com/document/d /…

3. Для достаточно больших таблиц добавление фильтров ( WHERE критериев) означает, что механизм БД должен выполнять больше работы, поэтому сам запрос займет больше времени. Особенно, если правильные индексы не установлены. Поэтому вам нужно прежде всего установить, сколько времени тратится в БД, прежде чем решать, где оптимизировать.

Ответ №1:

Я вижу несколько случаев

 a AND b OR c
 

Убедитесь , что вы хотите (a AND b) OR c , а не a AND (b OR c)

OR трудно оптимизировать.

Для organization_contact_reference :

 INDEX(contact_id, contact_sharing_level)
 

Если у вас не включен параметр «ascii_quotes», это должно быть синтаксической ошибкой:

 WHERE  "user".id = ...
 

organization_user_reference потребности

 INDEX(user_id, organization_id, default_contact_sharing_level)
 

ORDER BY job.is_primary DESC, job.start_time DESC может извлечь выгоду из

 INDEX(is_primary, start_time)
 

Не «пригодный для использования»: ... AND lower(email.email) IN ... используйте подходящий COLLATION on email , чтобы вам не нужно было использовать LOWER() .