#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()
.