哪一个是 quicker/optimized - 内部连接或分区 - 以获得聚合数据?

Which one is quicker/optimized - Inner Join or Partition By - to obtain Aggregated data?

在我的数据 'table1' 中,每个 app_id 有多个记录。我正在尝试获取最新的 app_id 条目。就性能和内存使用而言,考虑以下哪一项查询会更快或更好?目前,我在 AWS 服务器上工作并使用 PostgreSQL。

查询 1:

SELECT b.* 
FROM 
    (SELECT app_id, max(datetime) as datetime
    from table1
    group by 1) a
INNER JOIN 
    (SELECT * 
    from table1) b
ON a.app_id = b.app_id AND a.datetime = b.datetime

查询 2:

SELECT * 
FROM 
    (SELECT *, row_number() over (partition by app_id order by datetime DESC 
    NULLS LAST) as num FROM table1) sub
WHERE sub.num=1

"which is faster" 的正确答案是尝试对您的数据和系统进行查询。

也就是说,有一些考虑因素支持 row_number()。特别是,window 函数不是数据库中的 "accidental" 功能。添加新的字符串函数只是一个函数,该函数可能会优化也可能不会优化。

另一方面,window 函数需要 rewriting/redesigning 数据库引擎的一些基本组件。一般来说,这是在考虑性能的情况下完成的。所以,我通常发现 window 函数比等效构造更快。

具有讽刺意味的是,我经常发现(跨数据库)的唯一例外情况适用于您的情况。而且,它没有使用 joingroup by。相反,它是:

select t1.*
from table1 t1
where t1.datetime = (select max(tt1.datetime)
                     from table1 tt1
                     where tt1.app_id = t1.app_id
                    );

以及 table1(app_id, datetime) 上的索引。

性能改进的基本原因是扫描 table1 一次并在每一行进行索引查找。

join/group by 多次扫描 table,聚合成本很高。 row_number() 版本扫描 table(或索引),计算值,然后将值带回每一行——类似于数据的两次扫描。