0

我正在查询一个有几百万行的表。当我使用带有=的子选择时

select *
from "parcels" 
where "parcel_id" = (select "parcel_id" 
                     from "parcels_properties" 
                     where "property_id" = '178528')

索引将被使用并在 2 秒内返回。

这一点,显然当子查询有多个结果时,我需要使用WHERE IN. 然后它不会使用索引并给我 10+ 秒。

select * 
from "parcels" 
where "parcel_id" in (select "parcel_id" 
                      from "parcels_properties" 
                      where "property_id" = '178528')

解释:

"Hash Join  (cost=82047.73..357097.98 rows=2019856 width=170)"
"  Hash Cond: ((parcels.parcel_id)::text = (parcels_properties.parcel_id)::text)"
"  ->  Seq Scan on parcels  (cost=0.00..241975.11 rows=4039711 width=170)"
"  ->  Hash  (cost=82045.23..82045.23 rows=200 width=38)"
"        ->  HashAggregate  (cost=82043.23..82045.23 rows=200 width=38)"
"              Group Key: (parcels_properties.parcel_id)::text"
"              ->  Gather  (cost=1000.00..81970.73 rows=28999 width=38)"
"                    Workers Planned: 2"
"                    ->  Parallel Seq Scan on parcels_properties  (cost=0.00..78070.83 rows=12083 width=38)"
"                          Filter: ((property_id)::text = '178528'::text)"

在本说明的第 3 行,使用了 a Seq Scanon parcelstable,而不是parcel_id index?

还有一件事,这是在 AWS RDS 上

如果我使用几乎相同的设置在本地数据库上运行相同的 SQL(只有 RDS 是 v14,本地是 v12),它会使用索引并立即返回。

在 parcels 表上创建索引:

  • parcel_id

在 parcels_properties 表上创建索引:

  • parcel_id
  • property_id

那么有人可以帮我解决这个问题吗?

谢谢你。

更新

这样做将对 Parcels 表进行排序强制索引扫描

SET enable_seqscan = OFF;

SELECT *
FROM parcels p
WHERE EXISTS (
    SELECT 1
    FROM parcels_properties pp
    WHERE pp.parcel_id = p.parcel_id AND property_id = '178528'
);
4

2 回答 2

1

您从未告诉我们您定义了哪些索引,但无论如何我都会使用存在逻辑来表达您的查询:

SELECT *
FROM parcels p
WHERE EXISTS (
    SELECT 1
    FROM parcels_properties pp
    WHERE pp.parcel_id = p.parcel_id AND property_id = '12345'
);

此查询应受益于以下索引parcels_properties

CREATE INDEX idx_pp ON parcel_properties (property_id, parcel_id);
于 2022-01-28T09:48:03.197 回答
0

对于任何人将来都可能遇到同样的问题。尝试VACUUM您的数据库。

我做了一个完整VACUUM的数据库,它工作。

 vacuumdb --echo --full --verbose --analyze -h yourdbhost -p 5432 -U your username -d yourdbname
于 2022-01-28T11:21:49.790 回答