postgresql 不同时间范围的同一查询的执行时间不同

igetnqfo  于 2023-01-05  发布在  PostgreSQL
关注(0)|答案(1)|浏览(220)

我在一个使用WHERE datetime BETWEEN datetimeA and datetimeB的Postgres 12服务器上运行了这个查询,datetimeAdatetimeB之间的时间差总是30分钟,涉及的数据量没有太大的差异,但是的执行时间却有很大的不同:

  1. WHERE servertime between '2022-12-01 04:00:00' and '2022-12-01 04:30:00'(5秒)
  2. WHERE servertime between '2022-12-29 04:00:00' and '2022-12-29 04:30:00'(4分钟)
    月初日期的执行时间总是很快,当日期接近月底时,执行时间会变慢很多。
    以下是完整查询:
select p2.id as positionid, p2.stationid, p.servertime, p.servertime_max, p.geofenceid 
, p2.latitude, p2.longitude, datanum 
from( 
                select min(p.servertime) as servertime, max(p.servertime) as servertime_max 
                , p.deviceid, count(p.id) as datanum, p.geofenceid                  
                from tc_positions p 
                join tc_devices d on d.id=p.deviceid 
                join tc_stations st on st.id=p.stationid 
                where 
                p.speed <= 50 
                and st.stationcategory=200 
                and servertime between '2022-12-28 04:00:00' and  '2022-12-28 04:30:00'
                group by p.deviceid, p.geofenceid, p.stationid
                    --total data involved 180 rows
) p 
join ( 
                select * from tc_positions where            
                servertime between '2022-12-28 04:00:00' and  '2022-12-28 04:30:00'
                --total data involved 13.000 rows 
) p2 on p2.servertime=p.servertime and p2.deviceid=p.deviceid and p2.geofenceid=p.geofenceid 
where datanum>0;

在测试查询并在同一日期运行查询时,我停止了所有其他到数据库的连接和进程,但使用了不同的WHERE条件(无论何时运行查询,如果条件中的日期范围较小,日期总是很快,尽管数据库服务器当前正在处理繁重的读/写连接)。
为什么会有这种行为?可能是内部Postgres索引或其他东西使查询像这样运行。我希望在时间范围相同的情况下,任何日期的执行时间都是相同的。

pftdvrlh

pftdvrlh1#

这个更简单的查询应该是等效的,而且速度更快:

SELECT DISTINCT ON (p.deviceid, p.geofenceid, p.stationid)
       p.id AS positionid
     , p.geofenceid, p.deviceid, p.stationid
     , p.latitude, p.longitude
     , p.servertime
     , max(p.servertime) OVER w AS servertime_max
     , count(*) OVER w AS datanum
FROM   tc_positions p
JOIN   tc_stations st ON st.id = p.stationid
WHERE  p.speed <= 50
AND    st.stationcategory = 200
AND    p.servertime BETWEEN '2022-12-28 04:00:00' AND '2022-12-28 04:30:00'
WINDOW w AS (PARTITION BY p.deviceid, p.geofenceid, p.stationid)
ORDER  BY p.deviceid, p.geofenceid, p.stationid, p.servertime;

这可以在单个SELECT中完成,因为DISTINCT ON在窗口函数 * 之后 * 应用。
关于SELECT查询中的事件序列:

  • 在应用LIMIT之前获取结果计数的最佳方法

关于DISTINCT ON

  • 是否选择每个GROUP BY组中的第一行?

我完全删除了tc_devices的连接:似乎是无用的(除非该连接可以消除行)。
并且我在DISTINCT步骤中包含了stationid,以替换您的GROUP BY(这样您可以为每个stationid获得单独的行)。
至于为什么一个时间范围比另一个快:可能是不同的查询计划。但是如果没有执行计划,这是不可能的...

相关问题