【问题标题】:PostgreSQL timestamps - indexingPostgreSQL 时间戳 - 索引
【发布时间】:2012-05-23 09:06:19
【问题描述】:

我正在运行一个查询,我在其中查找一条记录,并在一段时间后查找另一条记录。

表定义:

(
  id integer primary key,
  gpsstatus character(2),
  datetime timestamp without time zone,
  lat numeric(9,6),
  lon numeric(9,6),
  alt numeric(9,4),
  time integer,
  datafileid integer,
  shape geometry,
  speed double precision,
  dist double precision,
  shape_utm geometry,
  lokalitet character(128),
  cowid integer
)

datetime、lokalitet、cowid、gpsstatus、shape 和 shape_utm 上有 gist-index 索引。

这些点应该每 5 秒采样一次,所以我尝试这样做

select <something more>,p1.timestamp 
from table p1, table p2 
where p1.timestamp + interval '5 secound' = p2.timestamp

运行得相当快,但后来我发现由于采样中的抖动,我丢失了很多点,因此这些点可能相隔 4 到 6 秒。

然后我尝试了:

where    (p2.timestamp, interval'0 second')
overlaps (p1.timestamp + interval '4 second', interval '2 second')

这需要很长时间。我还尝试了更简单的解决方案:

WHERE p1.timestamp + interval '4 second' <= p2.timestamp
AND   p1.timestamp + interval '6 second' >= p2.timestamp

这也导致了无法使用的缓慢。

时间戳字段有一个正常的索引。是否有一种特殊的索引可以使该查询可用?

此刻的查询:

SELECT
    p1.cowid,
    p1.datetime,
    st_distance(p1.shape_utm, lead(p1.shape_utm)
      OVER (ORDER BY p1.datetime)) AS meters_obs,
    st_distance(p1.shape_utm, lead(p1.shape_utm, 720)
      OVER (ORDER BY p1.datetime)) AS meters_hour,
    observation.observation
  FROM (gpspoint p1 LEFT JOIN observation
                           ON (observation.gpspointid = p1.id)),
       status
  WHERE p1.gpsstatus = status.id
    AND status.use = true;

我还可以通过询问一些特定的时间间隔来获得可接受的查询时间。

【问题讨论】:

  • 只有 4 或 5 或 6 秒这三种可能性吗?或者也可以有小数秒?
  • 第一条和第二条记录之间可能有更多您不想检索的记录?如果没有,您只需要检索时间戳高于第一条记录的较早记录。
  • @Mark Byers:只有三种可能,时间戳被截断为秒。 - 是的,我刚刚发现使用链式 ors 或 in() 运行得更快,尽管 sql 变得非常丑陋......
  • @Pablo:中间可能有记录(尽管正如我所描述的那样,没有记录),但我还需要看看在更长的时间间隔内会发生什么。但无论如何,我如何在未知秒数后找到下一条记录?有吗?
  • @MortenSickel:“如何在未知秒数后找到下一条记录?” Errr....你读过 Quassnoi 的回答吗?

标签: sql postgresql timestamp range


【解决方案1】:

如果你只想要以前的记录,你可以这样做:

SELECT  p, LAG(p) OVER (ORDER BY timestamp) AS pp
FROM    table p
ORDER BY
        timestamp

如果您需要在当前秒前记录46,请使用:

SELECT  p1.*, p2.*
FROM    table p1
LEFT JOIN
        table p2
ON      p2.timestamp BETWEEN p1.timestamp - '4 seconds'::INTERVAL
                         AND p1.timestamp - '6 seconds'::INTERVAL
ORDER BY
        p1.timestamp

如果它们都在范围内,这可能会返回多个先前的记录。

【讨论】:

  • 谢谢!在这里很新,我仍然无法为您的答案 +1。稍后我会回到那个:-)
  • @MortenSickel:我会伸出援手。
  • 虽然,事实证明 BETWEEN ... AND 使性能再次无法使用...(但是,我在那里学到了一些非常有用的技巧)数据库大约有 300 万行,我我要提取其中的 7000 到 10000 个。所有相关字段都被编入索引。
  • @Erwin Brandstetter:谢谢:-)
  • @MortenSickel: BETWEEN 使优化器注定要使用嵌套循环,这对于这种查询来说效率很低。您能否发布您的确切查询和表格定义?
猜你喜欢
  • 2016-03-21
  • 1970-01-01
  • 2015-06-27
  • 2019-01-27
  • 2015-03-01
  • 2013-06-20
  • 1970-01-01
  • 2018-10-07
  • 1970-01-01
相关资源
最近更新 更多