Не удалось придумать лучший заголовок для подробного описания проблемы. У меня есть две таблицы core_question
и core_team_worker
.
core_question
имеет два столбца id int4
и team_id int4
.
core_team_worker
имеет три столбца id int4
, worker_id int4
, team_id int4
.
Таким образом, с помощью этого core_team_worker
можно определить отношения между многими работниками и командами.
Теперь у меня есть следующий запрос, который мне нужно оптимизировать, нужно получить один уточняющий вопрос в порядке, полученном для указанного работника.
select q.id
from core_question q
join core_team_worker tw on tw.team_id = q.team_id
where tw.worker_id = 18 -- this is where I put the worker id, let's say 18 for example.
order by q.team_id asc, q.id asc
limit 1;
Теперь с 1,6 миллионами записей я получаю 830 мс на этот запрос. У меня есть следующие индексы баз данных:
У меня есть индексы b-дерева для первичных ключей и внешних ключей id, team_id
для core_question и id, team_id, worker_id
для core_team_worker. В дополнение к этому я создал многостолбцовый индекс для core_question, чтобы оптимизировать этот запрос, который прекрасно работает:
select q.id from core_question q
where q.team_id = 4
order by q.team_id asc, q.id asc
limit 1;
Вот код для многостолбцового индекса
create index core_question_team_id_idx on core_question (team_id asc nulls last, id asc nulls last);
Теперь, если Я удаляю order by
или фильтр на worker_id = 18
Я получаю время отклика 1 мс, что идеально. Если бы я мог создать индекс, включающий обе таблицы, что-то вроде (team_id, worker_id, question_id)
, которое помогло бы с этим запросом, но я понимаю, что такой индекс невозможен.
Я потратил довольно много времени, пытаясь оптимизировать этот запрос, но я все еще могу никуда не денется Как бы оптимизировать этот запрос?
Вот результат анализа объяснения:
Limit (cost=0.57..0.69 rows=1 width=8) (actual time=486.687..486.689 rows=1 loops=1)
-> Nested Loop (cost=0.57..53378.10 rows=473106 width=8) (actual time=486.686..486.686 rows=1 loops=1)
Join Filter: (q.team_id = tw.team_id)
Rows Removed by Join Filter: 1130118
-> Index Only Scan using core_question_team_id_idx on core_question q (cost=0.43..28924.18 rows=1630117 width=8) (actual time=0.022..150.151 rows=1130119 loops=1)
Heap Fetches: 0
-> Materialize (cost=0.15..2.17 rows=1 width=4) (actual time=0.000..0.000 rows=1 loops=1130119)
-> Index Scan using core_team_worker_worker_id_823a9ecc on core_team_worker tw (cost=0.15..2.17 rows=1 width=4) (actual time=0.003..0.004 rows=1 loops=1)
Index Cond: (worker_id = 18)
Planning Time: 0.374 ms
Execution Time: 486.723 ms