I have a Messages
table with user_id
field (string). A query for total unique users is extremely slow with over a million records.
Message.where(created_at: start_date..end_date).select(:user_id).distinct(:user_id).count
=> (120145.6ms) SELECT DISTINCT COUNT(DISTINCT "messages"."user_id") FROM "messages" WHERE ("messages"."created_at" BETWEEN '2016-05-14 04:00:00.000000' AND '2016-06-13 03:59:59.999000')
I have indexes on user_id
& created_at
, but postgres doesn't seem to use them:
Schema
add_index "messages", ["user_id"], name: "index_messages_on_user_id", using: :btree
add_index "messages", ["created_at"], name: "index_messages_on_created_at", using: :btree
PG Explain
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=56111.04..56291.89 rows=18085 width=29)
Group Key: user_id
-> Seq Scan on messages (cost=0.00..52215.65 rows=1558153 width=29)
Filter: ((created_at >= '2016-05-14 04:00:00'::timestamp without time zone) AND (created_at <= '2016-06-13 03:59:59.999'::timestamp without time zone))
(4 rows)
Why are the indexes not used? Any tips for speeding up the query?