Prawdopodobnie nie chcesz tego słyszeć, ale najlepszym sposobem na przyspieszenie SELECT DISTINCT
jest unikanie go DISTINCT
tego. W wielu przypadkach (nie wszystkie!) Można tego uniknąć dzięki lepszemu projektowaniu bazy danych lub lepszym zapytaniom.
Czasami GROUP BY
jest szybszy, ponieważ wymaga innej ścieżki kodu.
W twoim szczególnym przypadku nie wydaje się, że możesz się go pozbyć DISTINCT
. Ale możesz obsługiwać zapytanie za pomocą specjalistycznego indeksu, jeśli masz wiele tego rodzaju zapytań:
CREATE INDEX foo ON events (project_id, "time", user_id);
Dodawanie user_id
jest przydatne tylko wtedy, gdy otrzymujesz z tego skany tylko indeksowe . Kliknij link, aby uzyskać szczegółowe informacje. Usunąłby kosztowny skan stosów bitmap ze swojego planu zapytań, który zajmuje 90% czasu zapytania.
Twój EXPLAIN
wynik mówi mi, że zapytanie musi skondensować 2491 różnych użytkowników z pół miliona pasujących wierszy. Nie stanie się to superszybkie, bez względu na to, co robisz, ale może być znacznie szybsze.
Jeśli przedziały czasowe w twoich zapytaniach są zawsze takie same, MATERIALIIZED VIEW
składanie user_id
na per (project_id, <fixed time intervall>)
byłoby daleko. Nie ma tam jednak szansy w różnych odstępach czasu. Może mógłbyś co najmniej spasować użytkowników na godzinę lub inną minimalną jednostkę czasu, a to zapewniłoby wystarczającą wydajność, aby zagwarantować znaczne obciążenie.
Nitpick:
Najprawdopodobniej prognozy "time"
powinny być naprawdę:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
Poza:
nie używaj time
jako identyfikatora. To słowo zastrzeżone w standardowym języku SQL i podstawowy typ w Postgres.