Database PostgreSQL-与CTE一起查询多个值时不使用索引

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 (

我最近修改了数据库中的“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
    (
    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秒。改进它:没有人会注意到——永远不会。谢谢你,莫尔斯莫和保镖。我有较少的本地数据,并试图优化生产问题,这不是一个理想的情况。