【问题标题】:Slow activerecord/postgres query not utilizing index缓慢的 activerecord/postgres 查询不使用索引
【发布时间】:2016-10-13 00:03:40
【问题描述】:

我有一个带有user_id 字段(字符串)的Messages 表。对于超过一百万条记录,查询唯一用户总数非常慢。

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')

我在 user_idcreated_at 上有索引,但 postgres 似乎没有使用它们:

架构

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 解释

                                                                        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)

为什么不使用索引?有什么加快查询速度的技巧吗?

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord


    【解决方案1】:

    索引可能没有足够的选择性,所以 Postgres 决定它需要读取整个表。对于您的查询,我建议在messages(created_at, user_id) 上建立索引。鼓励 Postgres 使用索引而不是原始数据,因为它是一个覆盖索引。

    另一个想法是使created_at(或created_at, user_id)成为聚集索引。这可能不会影响插入性能,因为新记录将具有更高的 created_at 值并且无论如何都会在最后。这将减少 I/O。

    【讨论】:

    • 我试过messages(created_at, user_id),它似乎也忽略了那个索引:(
    • @mnort9 。 . .尝试删除select distinct。这个查询没有意义,它可能会混淆优化器。
    • 没有select,我可以使用Message.distinct.count(:user_id) 构建AR 查询,但它会产生相同的SELECT DISTINCT sql
    • 我想我明白了!此查询的性能要好得多(585.5ms) SELECT COUNT(*) FROM (SELECT DISTINCT user_id FROM messages)。参考:stackoverflow.com/questions/11250253/…
    • 哦,对了。 . . Postgres 和 Hive 在它们的优化器中都有同样的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多