[英]Why doesn't Postgresql use index for IN query?
我有一个表social_accounts
,在facebook_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扫描最终将变得最便宜。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.