Database PostgreSQL-与CTE一起查询多个值时不使用索引
我最近修改了数据库中的“resources”表,以便支持多个版本的资源 “资源”架构: 我在“id”列上有一个索引,在“parent\u res\u id”列上有另一个索引 我经常使用的查询是获取资源的所有相关信息:Database PostgreSQL-与CTE一起查询多个值时不使用索引,database,postgresql,performance,indexing,Database,Postgresql,Performance,Indexing,我最近修改了数据库中的“resources”表,以便支持多个版本的资源 “资源”架构: 我在“id”列上有一个索引,在“parent\u res\u id”列上有另一个索引 我经常使用的查询是获取资源的所有相关信息: WITH r2(id) AS ( SELECT r2.parent_res_id FROM resources r2 WHERE r2.id IN ( 2, 3 ) ) SELECT r.id FROM resources r WHERE (
WITH r2(id) AS (
SELECT r2.parent_res_id
FROM resources r2
WHERE r2.id IN ( 2, 3 )
)
SELECT r.id
FROM resources r
WHERE
(
r.id IN ( 2, 3 )
OR
r.parent_res_id IN ( 2, 3 )
OR
r.id IN (SELECT r2.id FROM r2)
OR
r.parent_res_id IN (SELECT r2.id FROM r2))
;
虽然当我解释分析这个查询时,Postgres正在进行seq扫描,而不是在主查询中使用索引,并且当我在子句中只传递了一个参数时,只在CTE中使用它
只有1个参数时查询计划:
Seq Scan on resources r (cost=8.21..21.25 rows=114 width=4) (actual time=0.077..0.078 rows=0 loops=1)
Filter: ((id = 240) OR (parent_res_id = 240) OR (hashed SubPlan 2) OR (hashed SubPlan 3))
Rows Removed by Filter: 153
Buffers: shared hit=13 dirtied=1
CTE f2
-> Index Scan using resources_pkey on resources r2 (cost=0.14..8.16 rows=1 width=4) (actual time=0.010..0.010 rows=0 loops=1)
Index Cond: (id = 240)
Buffers: shared hit=3 dirtied=1
SubPlan 2
-> CTE Scan on r2 r2_1 (cost=0.00..0.02 rows=1 width=4) (actual time=0.011..0.011 rows=0 loops=1)
Buffers: shared hit=3 dirtied=1
SubPlan 3
-> CTE Scan on r2 r2_2 (cost=0.00..0.02 rows=1 width=4) (actual time=0.000..0.000 rows=0 loops=1)
Planning Time: 0.122 ms
Execution Time: 0.104 ms
具有两个或多个参数的查询计划:
Seq Scan on resources r (cost=11.99..25.03 rows=115 width=4) (actual time=0.097..0.119 rows=11 loops=1)
Filter: ((id = ANY ('{211,270}'::integer[])) OR (parent_res_id = ANY ('{211,270}'::integer[])) OR (hashed SubPlan 2) OR (hashed SubPlan 3))
Rows Removed by Filter: 142
Buffers: shared hit=20
CTE f2
-> Seq Scan on resources r2 (cost=0.00..11.90 rows=2 width=4) (actual time=0.024..0.033 rows=1 loops=1)
Filter: (id = ANY ('{211,270}'::integer[]))
Rows Removed by Filter: 152
Buffers: shared hit=10
SubPlan 2
-> CTE Scan on r2 r2_1 (cost=0.00..0.04 rows=2 width=4) (actual time=0.029..0.039 rows=1 loops=1)
Buffers: shared hit=10
SubPlan 3
-> CTE Scan on r2 r2_2 (cost=0.00..0.04 rows=2 width=4) (actual time=0.000..0.000 rows=1 loops=1)
Planning Time: 0.132 ms
Execution Time: 0.152 ms
原因是什么?是否可以对其进行优化以获得更好的性能?您的表看起来非常小,可能有154个条目?这就解释了为什么博士后甚至不关心索引。您是否尝试插入更多的数据并查看发生了什么?在某些情况下,顺序查找可能比索引查找快得多。这个案子就是其中之一。一个小表可以用1个物理i/o(可能最慢但必要的操作)读取,但indexr至少需要2个物理i/o:1个用于索引,1个用于基表。另一种情况是一个大表和非选择性索引,其中必须读取相当大的百分比(10%)。这也是过早优化的情况,因为在这两种情况下,总时间都小于0.0003秒。改进它:没有人会注意到——永远不会。谢谢你,莫尔斯莫和保镖。我有较少的本地数据,并试图优化生产问题,这不是一个理想的情况。