TL; DR
Я получаю сообщение об ошибке тайм-аута на производстве:
OperationalError: (QueryCanceledError) canceling statement due to statement timeout CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."tableY" x WHERE $1 OPERATOR(pg_catalog.=) "tableX_id" FOR KEY SHARE OF x" 'DELETE FROM tableX WHERE tableX.id = %(id)s' {'id': 42}
и основной причиной является SELECT 1 FROM ONLY "public"."tableY" x
, потому что по полю tableX_id нет индекса. Я пытаюсь выяснить, откуда исходит этот запрос, мне не нужна эта проверка.
Полное объяснение
У меня есть 2 таблицы, tableX и tableY, и отношение, определенное в TableY в sqlalchemy как:
class TableY(Base):
...
tableX = relationship(
'TableX',
backref=backref(
'rows_y',
uselist=True,
lazy='dynamic',
),
uselist=False,
)
и в SQL как
create table if not exists tableY
(
...
tableX_id integer not null
constraint fk_tableX_id_tableY
references state_purchase
on update cascade on delete restrict,
)
Я пытаюсь удалить строку из таблицы
tableX_obj.delete()
SQLAlchemy пытается удалить также все связанные строки (с внешним ключом), поэтому ДО выполнения запроса DELETE он выполняет
SELECT id FROM tableY where tableX_id=42
но tableY - это таблица отношений "многие ко многим", поэтому у нее нет индекса для поля tableX_id - что приводит к TIMEOUT.
Создание индекса не было хорошим решением, потому что оно будет бесполезным: я уверен, что когда я делаю DELETE, не будет никаких связанных записей, поэтому у меня будет довольно большой индекс, который НЕ будет содержать никаких релевантных Информация. Он будет содержать только информацию о мусоре.
Итак, я хотел, чтобы БД справилась с этой ситуацией, и добавил passive_deletes=True
state_purchase = relationship(
'StatePurchase',
backref=backref(
'recommendations',
uselist=True,
lazy='dynamic',
passive_deletes=True,
),
uselist=False,
)
Казалось, проблема решена, НО теперь я получаю новую ошибку тайм-аута на производстве:
OperationalError: (QueryCanceledError) canceling statement due to statement timeout CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."tableY" x WHERE $1 OPERATOR(pg_catalog.=) "tableX_id" FOR KEY SHARE OF x" 'DELETE FROM tableX WHERE tableX.id = %(id)s' {'id': 42}
Что может выполнить этот запрос? Это происходит от SQLAlchemy? Если так, как я могу отключить это?
PostgreSQL 9.4
SQLAlchemy 0.9.8 (да, я знаю :()