为什么Postgresql不对IN查询使用索引?

我有一个表social_accountsfacebook_id其中列上有部分索引user_id IS NULL

如果我执行简单查询WHERE facebook_id = '123',则使用索引:

 => EXPLAIN for: SELECT "social_accounts".* FROM "social_accounts"  WHERE (user_id IS NOT NULL) AND "social_accounts"."facebook_id" = '123'

QUERY PLAN

--------------------------------------------------------------------------------------------------------------

Index Scan using index_social_accounts_on_facebook_id on social_accounts (cost=0.00..8.28 rows=1 width=345)

Index Cond: ((facebook_id)::text = '123'::text)

Filter: (user_id IS NOT NULL)

但是如果我使用IN它进行查询,则不会使用索引:

 => EXPLAIN for: SELECT "social_accounts".* FROM "social_accounts"  WHERE (user_id IS NOT NULL) AND "social_accounts"."facebook_id" IN ('123', '456')

QUERY PLAN

---------------------------------------------------------------------------------------------------

Bitmap Heap Scan on social_accounts (cost=8.53..16.36 rows=2 width=345)

Recheck Cond: ((facebook_id)::text = ANY ('{123,456}'::text[]))

Filter: (user_id IS NOT NULL)

-> Bitmap Index Scan on index_social_accounts_on_facebook_id (cost=0.00..8.52 rows=2 width=0)

Index Cond: ((facebook_id)::text = ANY ('{123,456}'::text[]))

(5 rows)

为什么在第二种情况下不使用索引?有什么办法可以加快这个查询?

(请注意,在此示例中,我已截断了数组,并测试了更多元素,但结果却相同,缓慢)

回答:

实际上,它 正在 使用索引。只是做不同的事情。

索引扫描一行一行地访问,以随机顺序从一个磁盘页面到下一个磁盘页面来回移动。

位图索引扫描首先过滤要访问的磁盘页面,然后依次访问后者。重新检查条件是因为随后需要在每个页面中过滤掉无效的行。

对于极少数的行,索引扫描是最便宜的。对于更多行,位图索引扫描变得最便宜。对于更大的行数,seq扫描最终将变得最便宜。

以上是 为什么Postgresql不对IN查询使用索引? 的全部内容, 来源链接: utcz.com/qa/413589.html

回到顶部