Você provavelmente não quer ouvir isso, mas a melhor opção para acelerar SELECT DISTINCT
é evitar DISTINCT
começar. Em muitos casos (nem todos!), Isso pode ser evitado com um melhor design do banco de dados ou com melhores consultas.
Às vezes, GROUP BY
é mais rápido, porque leva um caminho de código diferente.
No seu caso particular , não parece que você possa se livrar deDISTINCT
. Mas você pode dar suporte à consulta com um índice especializado se tiver muitas consultas desse tipo:
CREATE INDEX foo ON events (project_id, "time", user_id);
A adição user_id
é útil apenas se você conseguir verificações somente de índice . Siga o link para detalhes. Removeria o caro verificação de heap de bitmap do seu plano de consulta, que consome 90% do tempo da consulta.
Sua EXPLAIN
saída me diz que a consulta precisa condensar 2.491 usuários distintos em meio milhão de linhas correspondentes. Isso não se tornará super-rápido, não importa o que você faça, mas pode ser substancialmente mais rápido.
Se os intervalos de tempo em suas consultas forem sempre os mesmos, uma MATERIALIIZED VIEW
dobra user_id
por(project_id, <fixed time intervall>)
percorrerá um longo caminho. Não há nenhuma chance com intervalos de tempo variados. Talvez você possa pelo menos dobrar os usuários por hora ou alguma outra unidade de tempo mínima, e isso compraria desempenho suficiente para garantir a sobrecarga considerável.
Nitpick:
Muito provavelmente, os predicados "time"
devem realmente ser:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
Lado:
Não use time
como identificador. É uma palavra reservada no SQL padrão e um tipo básico no Postgres.