Я ожидал новых функций PostgreSQL 9.5 и очень скоро обновил нашу базу данных. Но я был очень удивлен, когда я обнаружил, чтоПочему CUBE, ROLLUP и GROUPING SETS PostgreSQL 9.5 будут медленнее, чем эквивалент UNION?
SELECT col1, col2, count(*), grouping(col1,col2)
FROM table1
GROUP BY CUBE(col1, col2)
запроса на нашем наборе данных на самом деле работает гораздо медленнее (~ 3 секунды), чем сумма длительностей запросов для эквивалентных данных (~ 1second общий для всех 4-х запросов, 100-300ms каждый). Оба столбца col1 и col2 имеют на них индексы.
Ожидается ли это (что означает, что функция больше связана с совместимостью, чем с производительностью прямо сейчас)? Или это может быть изменено?
Вот пример на вакуумированной производственной таблице:
> explain analyze select service_name, state, res_id, count(*) from bookings group by rollup(service_name, state, res_id);
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=43069.12..45216.05 rows=4161 width=24) (actual time=1027.341..1120.675 rows=428 loops=1)
Group Key: service_name, state, res_id
Group Key: service_name, state
Group Key: service_name
Group Key:()
-> Sort (cost=43069.12..43490.18 rows=168426 width=24) (actual time=1027.301..1070.321 rows=168426 loops=1)
Sort Key: service_name, state, res_id
Sort Method: external merge Disk: 5728kB
-> Seq Scan on bookings (cost=0.00..28448.26 rows=168426 width=24) (actual time=0.079..147.619 rows=168426 loops=1)
Planning time: 0.118 ms
Execution time: 1122.557 ms
(11 rows)
> explain analyze select service_name, state, res_id, count(*) from bookings group by service_name, state, res_id
UNION ALL select service_name, state, NULL, count(*) from bookings group by service_name, state
UNION ALL select service_name, NULL, NULL, count(*) from bookings group by service_name
UNION ALL select NULL, NULL, NULL, count(*) from bookings;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Append (cost=30132.52..118086.91 rows=4161 width=32) (actual time=208.986..706.347 rows=428 loops=1)
-> HashAggregate (cost=30132.52..30172.12 rows=3960 width=24) (actual time=208.986..209.078 rows=305 loops=1)
Group Key: bookings.service_name, bookings.state, bookings.res_id
-> Seq Scan on bookings (cost=0.00..28448.26 rows=168426 width=24) (actual time=0.022..97.637 rows=168426 loops=1)
-> HashAggregate (cost=29711.45..29713.25 rows=180 width=20) (actual time=195.851..195.879 rows=96 loops=1)
Group Key: bookings_1.service_name, bookings_1.state
-> Seq Scan on bookings bookings_1 (cost=0.00..28448.26 rows=168426 width=20) (actual time=0.029..95.588 rows=168426 loops=1)
-> HashAggregate (cost=29290.39..29290.59 rows=20 width=11) (actual time=181.955..181.960 rows=26 loops=1)
Group Key: bookings_2.service_name
-> Seq Scan on bookings bookings_2 (cost=0.00..28448.26 rows=168426 width=11) (actual time=0.030..97.047 rows=168426 loops=1)
-> Aggregate (cost=28869.32..28869.33 rows=1 width=0) (actual time=119.332..119.332 rows=1 loops=1)
-> Seq Scan on bookings bookings_3 (cost=0.00..28448.26 rows=168426 width=0) (actual time=0.039..93.508 rows=168426 loops=1)
Planning time: 0.373 ms
Execution time: 706.558 ms
(14 rows)
общее время сравнимо, но последний использует четыре сканирования, она не должна быть медленнее? «Внешнее слияние на диске» при использовании rollup() странно, у меня есть work_mem, установленный на 16M.
Покажите нам планы выполнения, используя 'объяснение (анализ, подробный)' –
. CUBE() на тех же столбцах дает еще более резкое различие – codesnik
Сортировка (внешний сортировка слияния) занимает большую часть времени, не так ли? 1027+ мс, или я неправильно понял это? –