我有一个时间刻度数据库的表TAB1,它有3列TAG、TIME、VALUE.时间和标签组成了表的主键:(时间,标签).

有500多万(50000,000)行.我需要找到最新的时间戳或最大(时间) for each N个标签.

以下是我try 过的几种方法,我将与大家分享我的经验:

  1. 内部查询
SELECT "time", "tag", "value"
FROM tab1 
WHERE ("tag","time") IN 
(SELECT "tag", MAX("time") FROM tab1 WHERE "tag" IN(tag1,tag2) GROUP BY "tag" );

这是给出的结果,但执行时间约为19秒,超出了可接受的限制

  1. 使用时间刻度数据库中的最后一个函数
SELECT tag, last(time, time), last(value,time)
FROM tab1
WHERE "tag" IN (tag1,tag2) GROUP BY "tag" ;

这是在10秒内输出的.

我需要找到另一个可行的解决方案,类似于第二个,可能表现更好.我try 了一些其他方法,如横向联接(3)、窗口函数(ROW_NUMBER,PARTITION)(4),但解决方案并不像预期的那样.

  1. 使用横向可以提供多个列的交叉,而不是像预期的那样具有最大时间的单个值.此外,它需要15秒才能执行,但可能是因为查询错误.
SELECT table1."tag", table1."time",table1."value" from tab1 as table1
join lateral (
    SELECT table2 ."tag",table2 ."time" from tab1 as table2   
    where table2."tag" = table1."tag"
    order by table2."time" desc limit 1
) p on true
where table1."tag" in (tag1,tag2)
  1. 在try 分区时,我想这样放limit 1:(Partition by Tag,Order by Time Desc Limit 1),但它给出了语法错误.如果没有限制1,我不会得到最新的时间.
SELECT * from 
( SELECT *, row_number() over (partition by tag order by time desc) as rownum
from  tab1) a
where tag in (tag1,tag2)

有没有人能建议3,4中的问题出了什么问题,或者是否还有其他 Select .

Index for my table is: enter image description here

推荐答案

有几件事将有助于这一点,并使这个查询更容易和更好地执行.第一个可能也是最重要的一个是表/超级表上的索引-它需要是标记、时间描述上的多列索引-时间的顺序并不重要,但索引中的列的顺序非常重要.tag必须是这里的第一列,因为我们需要首先按标记搜索,然后获取最新时间,如果我们有单独的索引,或者如果我们先按时间排序,这将是非常低效的.

您可以使用如下调用创建此索引:

CREATE INDEX ON tab1 (tag, "time" DESC);

下一件事是查询的表述.要获得每个标记的这一点,最简单的方法是编写一个DISTINCT ON查询.在时间尺度上,我们有optimized this sort of query个.这是一个有点奇怪的方式来表达它,所以可能会有一点难以找到.

基本上,您可以这样写它:

SELECT DISTINCT ON (tag) tag, "time" FROM tab1 ORDER BY tag, "time" DESC;

这应该会给你你想要的.这有点奇怪,但它会奏效的!

我不打算介绍其他方法,但大多数方法将随着指数的增加而显著改善,但这仍可能是表现最好的方法.

如果你愿意,请发表 comments ,说明这是如何运作的,以及它是否为你加快了速度!

Sql相关问答推荐

如何在一个范围内进行分组.""范围值在范围表中定义

如何从JSON数组中 Select 多个值

PostgreSQL使用SQL子查询在时间间隔内 Select 数据

如何将我的联接数据放入每个用户每月多行的列中?

Redshift PL/pgSQL循环中的参数化列名

PostgreSQL中递归CTE查询的故障过滤

Select 最频繁的值以及分组依据

如何创建snowflake表(动态查找数据类型)并从阶段加载(AWS S3)?

除了风格之外,还有什么理由更喜欢简单的CASE WHEN而不是搜索呢?

两个具有 NULL 值的表达式结果之间的差异

如何根据共同列值从两个表中包含列,但只包含左表中的行

SQL中如何转置表格 UNPIVOT是唯一的 Select 吗?

如何通过CROSS APPLY获取多级嵌套JSON属性的值?

joins 组合多个重复数据删除策略

连接表时避免重复

PostgreSQL Select 具有两列的自引用

如何在 Trino/Presto 中过滤掉 map 中的某些键?

如何刷新在视图之上创建的表

SQL:有没有办法根据另一列的数据细节过滤和形成另一列?

遍历数据,计算每个月最后三天的总和