首页 > 解决方案 > 优化复杂的 PostgreSQL 查询

问题描述

我正在尝试对几个表进行复杂的 SQL 连接:如下所示。我还包含了一个 dB 模式的图像。

考虑 table_1 -

e_id  name

1     a
2     b
3     c
4     d

和 table_2 -

e_id  date

1     1/1/2019
1     1/1/2020
2     2/1/2019
4     2/1/2019

在此处输入图像描述

这里的问题是性能。从表 2 - 4 中,我们只想要给定 e_id 的最新条目,但因为这些表包含历史数据(~>350 万行),所以速度很慢。我附上了一个示例,说明我们目前如何尝试实现这一目标,但它仅包括“table_1”与“table_x”的一个连接。我们按 e_id 分组并获得它的最大日期。我们考虑这样做的另一种方法是创建一个物化视图并从中提取数据并在一段时间后刷新它。欢迎任何改进。

from fds.region as rg
    inner join (
        select e_id, name, p_id
        from fds.table_1
        where sec_type = 'S' AND active_flag = 1
    ) as table_1 on table_1.e_id = rg.e_id
    inner join fds.table_2 table_2 on table_2.e_id = rg.e_id
    inner join fds.sec sec on sec.p_id = table_1.p_id
    inner join fds.entity ent on ent.int_entity_id = sec.int_entity_id
    inner join (
        SELECT int_1.e_id, int_1.date, int_1.int_price
        FROM fds.table_4 int_1
            INNER JOIN (
                SELECT e_id, MAX(date) date
                FROM fds.table_2
                GROUP BY e_id
            ) int_2 ON int_1.e_id = int_2.fsym_id AND int_1.date = int_2.date
    ) as table_4 on table_4.e_id = rg.e_id  
where rg.region_str like '%US' and ent.sec_type = 'P'
order by table_2.int_price
limit 500;

标签: sqlpostgresqljoin

解决方案


您可以简化此逻辑:

    (
        SELECT int_1.e_id, int_1.date, int_1.int_price
        FROM fds.table_4 int_1
            INNER JOIN (
                SELECT e_id, MAX(date) date
                FROM fds.table_2
                GROUP BY e_id
            ) int_2 ON int_1.e_id = int_2.fsym_id AND int_1.date = int_2.date
    ) as table_4

至:

(SELECT DISTINCT ON (int_1.e_id) int_1.*
 FROM fds.table_4 int_1
 ORDER BY int_1.e_id, int_1.date DESC
) table_4

这可以利用上的索引fds.table_4(e_id, date desc)——并且使用这样的索引可能会很快变坏。

您还需要用于连接和过滤的适当索引。但是,如果没有执行计划,就很难更具体。


推荐阅读