На стороне SQL это довольно просто. Я построил несколько таблиц для тестирования, используя только один идентификационный номер (для лиц); все остальные ключи были естественными ключами. Просмотр плана выполнения для этого запроса
select I.*, A.activity_placeholder, E.event_location, O.objective_placeholder
from event_invitations I
inner join activity A
on (I.activity_name = A.activity_name)
inner join events E
on (I.personal_id = E.personal_id
and I.activity_name = E.activity_name
and I.objective_deadline = E.objective_deadline
and I.event_time = E.event_time)
inner join personal_objectives O
on (I.personal_id = O.personal_id
and I.activity_name = O.activity_name
and I.objective_deadline = O.objective_deadline)
where I.person_invited_id = 2;
показывает, что dbms (PostgreSQL) использует индексы повсюду, за исключением последовательного сканирования event_invitations. Я уверен, что это потому, что я использовал очень мало данных, поэтому все эти таблицы легко помещаются в оперативную память. (Когда таблицы помещаются в ОЗУ, часто быстрее сканировать небольшую таблицу, чем использовать индекс.)
Оптимизатор оценивает стоимость каждой части запроса в 0,00, и вы не можете получить намного лучше, чем это. Фактическое время выполнения составило менее 0,2 миллисекунды, но это мало что значит.
Я уверен, что вы можете перевести это на SQLAlchemy. Дайте мне знать, если вы хотите, чтобы я опубликовал свои таблицы и образцы данных.