Я мог легко поверить, что запросы занимают так много времени. У вас есть таблица строк 29M, в которой вы работаете с несколькими группами и несколько раз связываетесь с собой в разных столбцах. Если вся таблица не помещается в память, может быть много страниц, которые не нужны с 1/7 строк. Работая внутрь, вы:
- Выбор из таблицы строк 29M на позиции = 0 и cnt_players = 6
- Двойная ссылка на таблицу строк 29M в столбце id_hand
- Фильтрация таблицы строк 29M дважды для cnt_players = 6 и позиций 0 и 8 и вычисление среднего значения flg_vpip по игроку
- Ссылка на сгруппированные результаты в id_hand для миллионов строк
Не могли бы вы разделить стол на отдельные? Что именно означают ваши поля и как будет выглядеть образец руки?
Вам нужны индексы как минимум для id_player, id_hand, position и cnt_players.
Возможно, было бы хорошо включить все поля в индекс. Я не уверен насчет postgresql, но SQL Server может пропустить загрузку реальных страниц данных таблицы, если все данные, необходимые для запроса, находятся в индексе. Поэтому, если бы у вас был индекс позиции, cnt_players, id_player и flg_vpip, ваши самые внутренние выборки, вероятно, были бы намного быстрее.
Я думаю, что лучшим способом было бы заранее рассчитать эти внутренние выборки в одну или две таблицы, если вы не собираетесь часто выполнять запрос.
select id_player, position, cnt_players,
ROUND(avg(flg_vpip::int)*25) AS avg_vpip
into auxtable
from holdem oldem
group by id_player, position, cnt_players
alter table auxtable add constraint PK_auxtable
primary key clustered (id_player, position, cnt_players)
Как это:
SELECT sbvpip*4 as smallbvpip,btnvpip*4 as buttonvpip, sum(amt_won)*400/count(*) AS winrate, count(*) as count
FROM holdem
JOIN (
SELECT id_player AS pid2, id_hand AS hid, sbvpip
FROM holdem
JOIN auxtable ON auxtable.id_payer = holdem.id_player
and auxtable.position = holdem.position
and auxtable.cnt_players = holdem.cnt_players
WHERE holdem.position = 8 AND holdem.cnt_players = 6
) AS auxtable2 ON hid = id_hand