【问题标题】:Query does not hit the index - are these the proper columns to index?查询未命中索引 - 这些是要索引的正确列吗?
【发布时间】:2019-10-03 03:51:56
【问题描述】:

以下对 Postgres 数据库的查询有时非常慢(4,000+ms):

EXPLAIN ANALYZE SELECT "sms".* FROM "sms" WHERE "sms"."From" = 'NUMBER1' AND "sms"."To" = 'NUMBER2' AND "sms"."SmsMessageSid" = 'UNIQUE_ID' ORDER BY "sms"."id" ASC LIMIT 1;

当我运行 psql 并分析查询时,结果如下:

Limit  (cost=5045.12..5045.12 rows=1 width=609) (actual time=57.011..57.011 rows=0 loops=1)
   ->  Sort  (cost=5045.12..5045.12 rows=1 width=609) (actual time=57.009..57.009 rows=0 loops=1)
         Sort Key: id
         Sort Method: quicksort  Memory: 25kB
         ->  Bitmap Heap Scan on sms  (cost=46.02..5045.11 rows=1 width=609) (actual time=56.993..56.993 rows=0 loops=1)
               Recheck Cond: (("To")::text = 'NUMBER1'::text)
               Filter: ((("From")::text = 'NUMBER2'::text) AND (("SmsMessageSid")::text = 'UNIQUE_ID'::text))
               Rows Removed by Filter: 2501
               Heap Blocks: exact=1230
               ->  Bitmap Index Scan on "index_sms_on_To"  (cost=0.00..46.02 rows=2623 width=0) (actual time=0.345..0.345 rows=2566 loops=1)
                     Index Cond: (("To")::text = 'NUMBER1'::text)

我创建了一个索引如下:

add_index "sms", ["id", "From", "To", "SmsMessageSid"], name: "on_id_from_to_sms_message_sid"

但是分析方法没有达到索引。我是否包含了错误的列?

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord indexing


    【解决方案1】:

    id 应该来最后。喜欢

    add_index "sms", ["From", "To", "SmsMessageSid", "id"], name: "on_id_from_to_sms_message_sid"
    

    通常:先相等,后取范围。相关:

    id 仍应附加,除非("From", "To", "SmsMessageSid") 的每个组合的行数很少。这样,Postgres 可以直接从索引顶部选择第一行 - 在 index scan 中,而不是像现在看到的 bitmap index scan

    相关:

    【讨论】:

    • 做到了!感谢您的建议和相关阅读 - 非常有帮助。
    【解决方案2】:

    尝试从索引中删除 id,即

    add_index "sms", ["From", "To", "SmsMessageSid"], name: "on_id_from_to_sms_message_sid"`
    

    根据https://www.postgresql.org/docs/9.5/indexes-multicolumn.html

    多列 B 树索引可用于涉及索引列的任何子集的查询条件,但当前导(最左侧)列存在约束时,索引效率最高。确切的规则是前导列上的等式约束,加上没有等式约束的第一列上的任何不等式约束,将用于限制扫描的索引部分。在索引中检查这些列右侧的列的约束,因此它们可以正确保存对表的访问,但不会减少必须扫描的索引部分。例如,给定 (a, b, c) 上的索引和查询条件 WHERE a = 5 AND b >= 42 AND c = 77 的索引条目将被跳过,但仍然必须扫描它们。这个索引原则上可以用于对 b 和/或 c 有约束而对 a 没有约束的查询——但是必须扫描整个索引,所以在大多数情况下,计划器更喜欢顺序表扫描而不是使用索引.

    【讨论】:

      猜你喜欢
      • 2017-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 2012-12-26
      相关资源
      最近更新 更多