使用varchar_pattern_ops索引而不是pkey索引的Django-Postgres WHERE查询

时间:2019-04-23 07:34:07

标签: django postgresql postgresql-9.5 database-indexes django-1.9

我在此表中有一个Django-Postgres设置-

class User(models.Model):
    id = models.CharField(max_length=255, primary_key=True)

运行迁移会在该字段上创建两个索引(这是Django在运行sqlmigrate时进行检查时自动执行的操作)-一个索引为pkey,另一个索引为varchar_pattern_ops-

\d+ "user";

Column|            Type          | Modifiers | Storage  | Stats target | Description 
------+--------------------------+-----------+----------+--------------+-------------
 id   |  character varying(255)  | not null  | extended |              | 

Indexes:
"user_pkey" PRIMARY KEY, btree (id)
"user_id_90845346_like" btree (id varchar_pattern_ops)

据我了解,如果我运行此查询

select * from "user" where id='id1234';

它应该使用user_pkey。而是使用user_id_90845346_like

explain analyze select * from "user" where id='id1234';

 Index Scan using "user_id_90845346_like" on "user"  (cost=0.41..8.43 rows=1 width=770) (actual time=0.033..0.0
33 rows=0 loops=1)
   Index Cond: ((id)::text = 'id1234'::text)
 Planning time: 1.335 ms
 Execution time: 0.072 ms
(4 rows)

我也没有看到任何强制Postgres使用索引的选项,但是我真正想知道的是为什么=搜索不使用主键。 like text%搜索不应该使用varchar_pattern_ops索引吗?

1 个答案:

答案 0 :(得分:1)

如果要建立索引的列是varchar列或其某些变体,则postgres驱动程序将始终选择varchar_pattern_ops索引。简而言之,因为您要建立索引的列包含字符串,所以驱动程序将在索引可用时选择最适合字符串的索引。如果将主键存储为整数,则驱动程序将使用btree索引。