查询未命中索引-这些是要索引的正确列吗?

时间:2019-05-15 23:28:25

标签: ruby-on-rails postgresql activerecord indexing

以下对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"

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

2 个答案:

答案 0 :(得分:3)

id应该排在最后。喜欢

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

通常:首先是平等,然后是范围。相关:

除非后面每个id的行数很少,否则仍应附加

("From", "To", "SmsMessageSid")。这样,Postgres可以直接从索引顶部选择第一行-在索引扫描中,而不是像现在看到的 bitmap索引扫描

相关:

答案 1 :(得分:0)

尝试从索引中删除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,则该索引必须从a = 5和b =的第一项开始扫描从42向上直到a = 5的最后一个条目。c> = 77的索引条目将被跳过,但是仍然必须对其进行扫描。原则上,该索引可用于对b和/或c有约束但对a无约束的查询,但是必须扫描整个索引,因此在大多数情况下,计划者宁愿使用顺序表扫描,也不愿使用索引

相关问题