PostgreSQL - 如何创建一个条件,记录当前记录日期和相同日期加上5分钟?

时间:2017-11-02 21:21:38

标签: postgresql performance

我有类似的东西。通过这部分代码,我检测车辆是否至少停了5分钟。 并且工作但是,随着大量数据,它开始变慢。 我做了很多测试,我确定我的问题出在not exists区块。

我的表:

CREATE TABLE public.messages
(
  id bigint PRIMARY KEY DEFAULT nextval('messages_id_seq'::regclass),
  messagedate timestamp with time zone NOT NULL,
  vehicleid integer NOT NULL,
  driverid integer NOT NULL,
  speedeffective double precision NOT NULL,
  -- ... few nonsense properties
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.messages OWNER TO postgres;

CREATE INDEX idx_messages_1 ON public.messages
 USING btree (vehicleid, messagedate);

我的疑问:

SELECT
    *
FROM
    messages m
WHERE
    m.speedeffective > 0
    and m.next_speedeffective = 0
    and not exists( -- my problem
        select id
        from messages
        where
            vehicleid = m.vehicleid
            and speedeffective > 5 -- I forgot this condition
            and messagedate > m.messagedate
            and messagedate <= m.messagedate + interval '5 minutes'
    )

我无法弄清楚如何以更高效的方式建立这种状况。

编辑第二天:

我在 second 表中添加了一个像这样的上一个表:

WITH messagesx as (
  SELECT
    vehicleid,
    messagedate
  FROM
    messages
  WHERE
    speedeffective > 5
)

现在效果更好。我认为我错过了一些细节。

2 个答案:

答案 0 :(得分:0)

通常,“NOT EXISTS”会降低查询速度,因为它需要对每个外部行进行完整的表扫描。尝试在连接中包含相同的功能(我试图在这里重写查询,而不知道表,所以我可能在这里犯了错误):

SELECT
    *
FROM
    messages m1
LEFT JOIN 
    messages m2
ON m1.vehicleid = m2.vehicleid AND m1.messagedate < m2.messagedate AND m1.messagedate <= m2.messagedate+interval '5 minutes'
WHERE
    speedeffective > 0
    and next_speedeffective = 0
    and m2.vehicleid IS NULL

请注意,NOT EXISTS被重写为未连接条件。

答案 1 :(得分:0)

根据这个答案:https://stackoverflow.com/a/36445233/5000827 阅读NOT INNOT EXISTSLEFT JOIN,其中join为NULL

对于PostgreSQL,NOT EXISTSLEFT JOIN 反加入并以相同的方式工作。 (这就是为什么@CountZukula答案的结果几乎与我的相同)

问题出在那种操作上:NestHash

所以,基于此:https://www.postgresql.org/docs/9.6/static/routine-vacuuming.html

  

PostgreSQL的VACUUM命令必须定期处理每个表,原因如下:

     
      
  1. 恢复或重复使用更新或删除的行占用的磁盘空间。

  2.   
  3. 更新PostgreSQL查询规划器使用的数据统计信息。

  4.   
  5. 更新可见性图,以加速仅索引扫描。

  6.   
  7. 防止由于事务ID环绕或多重ID环绕而导致丢失非常旧的数据。

  8.   

我制作了VACUUM ANALYZE消息表,同样的查询也很快。

所以,VACUUM PostgreSQL可以更好地决定。