Postgres делает намного больше, чем кажется (поддерживая согласованность данных для начала!)
Если значения не обязательно должны быть на 100% точными или если таблица обновляется редко, но вы часто выполняете этот расчет, вы можете захотеть заглянуть в Материализованные представления, чтобы ускорить его.
(Обратите внимание, я не использовал материализованные представления в Postgres, они выглядят немного странно, но могут подходить для вашей ситуации).
Материализованные представления
Также рассмотрите накладные расходы на фактическое соединение с сервером и двустороннюю передачу, необходимую для отправки запроса на сервер и обратно.
Я бы посчитал, что 200 мс для чего-то подобного довольно неплохо. Быстрый тест на моем сервере Oracle, с той же структурой таблицы, содержащей около 500 000 строк и без индексов, занимает от 1 до 1,5 секунд, что почти все просто оракул. высасывая данные с диска.
Реальный вопрос в том, достаточно ли 200 мс?
-------------- Подробнее --------------------
Мне было интересно решить эту проблему, используя материализованные представления, поскольку я никогда не играл с ними. Это в оракуле.
Сначала я создал MV, который обновляется каждую минуту.
create materialized view mv_so_x
build immediate
refresh complete
START WITH SYSDATE NEXT SYSDATE + 1/24/60
as select count(*),avg(a),avg(b),avg(c),avg(d) from so_x;
При обновлении строки не возвращаются
SQL> select * from mv_so_x;
no rows selected
Elapsed: 00:00:00.00
Как только он обновляется, он НАМНОГО быстрее, чем необработанный запрос
SQL> select count(*),avg(a),avg(b),avg(c),avg(d) from so_x;
COUNT(*) AVG(A) AVG(B) AVG(C) AVG(D)
---------- ---------- ---------- ---------- ----------
1899459 7495.38839 22.2905454 5.00276131 2.13432836
Elapsed: 00:00:05.74
SQL> select * from mv_so_x;
COUNT(*) AVG(A) AVG(B) AVG(C) AVG(D)
---------- ---------- ---------- ---------- ----------
1899459 7495.38839 22.2905454 5.00276131 2.13432836
Elapsed: 00:00:00.00
SQL>
Если мы вставим в базовую таблицу, результат не будет сразу просматриваться просмотром MV.
SQL> insert into so_x values (1,2,3,4,5);
1 row created.
Elapsed: 00:00:00.00
SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
SQL> select * from mv_so_x;
COUNT(*) AVG(A) AVG(B) AVG(C) AVG(D)
---------- ---------- ---------- ---------- ----------
1899459 7495.38839 22.2905454 5.00276131 2.13432836
Elapsed: 00:00:00.00
SQL>
Но подождите минутку или около того, и MV обновится за кулисами, и результат будет возвращен так быстро, как вы могли захотеть.
SQL> /
COUNT(*) AVG(A) AVG(B) AVG(C) AVG(D)
---------- ---------- ---------- ---------- ----------
1899460 7495.35823 22.2905352 5.00276078 2.17647059
Elapsed: 00:00:00.00
SQL>
Это не идеально. для начала, это не в реальном времени, вставки / обновления не будут видны сразу. Кроме того, у вас запущен запрос на обновление MV независимо от того, нужен он вам или нет (это можно настроить на любой период времени или по требованию). Но это показывает, насколько быстрее MV может показаться конечному пользователю, если вы можете жить со значениями, которые не совсем точны до второй.