Часть запроса PostgreSQL работает довольно медленно, и я не могу понять, почему.Почему LEFT JOIN работает медленно?
Полный запрос:
SELECT t.id FROM tests t
LEFT JOIN tests c ON c.parent_id IN (t.id, t.parent_id)
INNER JOIN responses r ON (
r.test_id IN (t.id, t.parent_id, c.id)
) WHERE r.user_id = 333
Есть указатели на tests.id
и tests.parent_id
.
Тесты содержат 28876 строк (из них 1282 WHERE parent_id IS NOT NULL
).
Часть запроса запрашивает 32098 строк, а занимает около 700 мс.
SELECT t.id FROM tests t
LEFT JOIN tests c ON c.parent_id IN (t.id, t.parent_id)
Остальная часть запроса занимает незначительное количество времени.
Любые идеи относительно того, почему это может быть медленным, или лучший способ добиться того же самого?
Спасибо!
ВЫБРАТЬ ВАРИАНТ()
PostgreSQL 9.1.9 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
EXPLAIN ANALYZE
(Примечание: это использует реальное имя таблицы, usability_tests
, которую я упростился tests
в предыдущих примерах.)
Nested Loop (cost=5.18..158692.45 rows=80 width=4) (actual time=107.873..5718.295 rows=103 loops=1)
Join Filter: ((r.usability_test_id = t.id) OR (r.usability_test_id = t.parent_id) OR (r.usability_test_id = c.id))
-> Nested Loop Left Join (cost=0.56..136015.63 rows=28876 width=12) (actual time=0.091..486.496 rows=32098 loops=1)
Join Filter: ((c.parent_id = t.id) OR (c.parent_id = t.parent_id))
-> Seq Scan on usability_tests t (cost=0.00..1455.76 rows=28876 width=8) (actual time=0.042..39.558 rows=28876 loops=1)
-> Bitmap Heap Scan on usability_tests c (cost=0.56..4.60 rows=4 width=8) (actual time=0.010..0.011 rows=0 loops=28876)
Recheck Cond: ((parent_id = t.id) OR (parent_id = t.parent_id))
-> BitmapOr (cost=0.56..0.56 rows=4 width=0) (actual time=0.008..0.008 rows=0 loops=28876)
-> Bitmap Index Scan on index_usability_tests_on_parent_id (cost=0.00..0.28 rows=2 width=0) (actual time=0.003..0.003 rows=0 loops=28876)
Index Cond: (parent_id = t.id)
-> Bitmap Index Scan on index_usability_tests_on_parent_id (cost=0.00..0.28 rows=2 width=0) (actual time=0.001..0.001 rows=0 loops=28876)
Index Cond: (parent_id = t.parent_id)
-> Materialize (cost=4.62..153.63 rows=39 width=4) (actual time=0.001..0.076 rows=70 loops=32098)
-> Bitmap Heap Scan on responses r (cost=4.62..153.44 rows=39 width=4) (actual time=0.053..0.187 rows=70 loops=1)
Recheck Cond: (user_id = 3649)
-> Bitmap Index Scan on index_responses_on_user_id (cost=0.00..4.61 rows=39 width=0) (actual time=0.040..0.040 rows=70 loops=1)
Index Cond: (user_id = 3649)
Total runtime: 5718.592 ms
Вы пытаетесь рекурсивно запросить иерархию в этой таблице? Если да, то для этого вам нужен CTE. –
Я хотел бы попробовать попробовать Союз с условиями, разделенными на два запроса. Могу ли я спросить, в чем цель проверки соответствия родительских идентификаторов, просто для того, чтобы убедиться, что вы каждый раз проверяете каждую запись в тестах? – ChrisProsser
@ChrisProsser Это только часть более крупного запроса, который выполняет дальнейшую фильтрацию на основе атрибутов объединенной таблицы 'c'. В отдельности я вижу, что результаты «DISTINCT» этого запроса ничем не отличаются от «SELECT id from tests». – doctororange