Anda mungkin tidak ingin mendengar ini, tetapi opsi terbaik untuk mempercepat SELECT DISTINCT
adalah menghindari DISTINCT
untuk memulainya. Dalam banyak kasus (tidak semua!) Dapat dihindari dengan desain database yang lebih baik atau pertanyaan yang lebih baik.
Terkadang, GROUP BY
lebih cepat, karena dibutuhkan jalur kode yang berbeda.
Dalam kasus khusus Anda , sepertinya Anda tidak bisa menyingkirkannya DISTINCT
. Tetapi Anda dapat mendukung kueri dengan indeks khusus jika Anda memiliki banyak pertanyaan seperti itu:
CREATE INDEX foo ON events (project_id, "time", user_id);
Menambahkan user_id
hanya berguna jika Anda hanya dapat memindai indeks saja . Ikuti tautan untuk detailnya. Akan menghapus Pemindaian Tumpukan Bitmap yang mahal dari paket kueri Anda, yang menghabiskan 90% waktu permintaan.
EXPLAIN
Output Anda memberi tahu saya bahwa kueri harus memadatkan 2.491 pengguna yang berbeda dari setengah juta baris yang cocok. Ini tidak akan menjadi super cepat, apa pun yang Anda lakukan, tetapi ini bisa jauh lebih cepat.
Jika interval waktu dalam kueri Anda selalu sama, MATERIALIIZED VIEW
lipat user_id
per (project_id, <fixed time intervall>)
akan jauh. Tidak ada kesempatan di sana dengan interval waktu yang bervariasi. Mungkin Anda bisa setidaknya melipat pengguna per jam atau unit waktu minimum lainnya, dan itu akan membeli kinerja yang cukup untuk menjamin overhead yang cukup besar.
Nitpick:
Kemungkinan besar, predikat pada "time"
seharusnya adalah:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
Selain:
Jangan gunakan time
sebagai pengidentifikasi. Ini adalah kata yang dilindungi undang - undang dalam SQL standar dan tipe dasar dalam Postgres.