1

我有 2 张桌子,大约是这样的:

Parent_table: Parent_id bigint, Loc geometry
Child_table: Child_id bigint, 
             parent_id bigint, 
             record_date timestamp, 
             value double precision, 
             category character varying(10)

我需要查询子表的子集以了解不同的条件(位置、日期范围、值范围、类别)。作为其中的一部分,我从父表中筛选出位置,然后想要获取所有匹配的记录

显而易见的方法是:

with limited_parents as
(
 select parent_id from parent_table where [location condition]
)
select [ columns ] from child_table where parent_id in 
         (select parent_id from limited_parents)
and [ other conditions for record_date, value, category ]

Child_table拥有超过 2 亿条记录,按年份划分。它具有 parent_key 的索引,并且其他列都按该顺序包含在索引中。

Parent_table有 <10k 记录。每个父级可以轻松拥有 > 1m+ 子记录(每个父级的子记录数广泛分布从几百到百万+)。在任何查询范围内(因此包含在该子选择中)的父集合可能从 1 到数百。

数据库目前是 Postgres 10。

该查询对于几年/分区的范围是有效的,但随着范围内日期数量的增加而变得明显变慢。

我可以自由调整索引和更改查询。有没有更有效的方法来做这个查询? (将两张表展平,并将位置放在子表上并在那里进行地理交叉点,使整个事情变慢了几个数量级)

4

1 回答 1

0

您的查询是以复杂且低效的方式编写的。特别是,CTE 是旧 PostgreSQL 版本中的优化器栅栏。

尝试这个:

SELECT [ columns ] FROM child_table AS c
WHERE EXISTS (SELECT 1 FROM parent_table AS p
              WHERE [location condition on p]
                AND p.parent_id = c.parent_id)
  AND [ other conditions for record_date, value, category ]

在大表的外键列上创建索引,以加快嵌套循环连接。设置work_mem为高以加快哈希连接。PostgreSQL 会自动选择最佳解决方案。

于 2021-03-25T11:35:15.720 回答