Напевно, ви не хочете цього чути, але найкращий варіант для прискорення - SELECT DISTINCTце уникати DISTINCT для початку. У багатьох випадках (не у всіх!) Цього можна уникнути за допомогою кращого дизайну баз даних або кращих запитів.
Іноді, GROUP BYшвидше, тому що він займає інший шлях коду.
У вашому конкретному випадку не здається, що ви можете позбутися DISTINCT. Але ви можете підтримати запит спеціалізованим індексом, якщо у вас є багато запитів такого типу:
CREATE INDEX foo ON events (project_id, "time", user_id);
Додавання user_idкорисно лише в тому випадку, якщо з цього ви отримаєте сканування , призначені лише для покажчиків . Докладніше перейдіть за посиланням. Видалить з плану запитів дорогий Bitmap Heap Scan , який забирає 90% часу запиту.
Ваша EXPLAIN висновок підказує мені, що запит має стиснути 2491 різних користувачів із півмільйона відповідних рядків. Це не стане надшвидким, що б ви не робили, але це може бути значно швидше.
Якщо інтервали часу у ваших запитах завжди однакові, MATERIALIIZED VIEWскладанняuser_id на (project_id, <fixed time intervall>)певний шлях пройде досить довго. Немає жодного шансу з різними інтервалами часу. Можливо, ви могли б принаймні скласти користувачів на годину чи якусь мінімальну одиницю часу, і це дозволить придбати достатню продуктивність, щоб гарантувати значні витрати.
Нітпік:
Скоріш за все, предикати "time"повинні бути:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
Убік:
Не використовуйте timeяк ідентифікатор. Це зарезервоване слово у стандартному SQL та базовий тип у Postgres.