PostgreSQL MAX()内部查询确实很慢

时间:2016-02-08 12:51:03

标签: sql postgresql greatest-n-per-group query-performance

我目前的任务是优化在非常大的数据集上运行的一些SQL查询。我有下面的查询,我试图优化,但目前正在与它斗争

查询需要大约40-45分钟才能回归,答案显然是不可接受的。随着数据集在数据库中的增长,它甚至会花费更长的时间。

我相信它的内部MAX()函数会大大减慢查询速度吗?

感谢您提供更好,更快的查询帮助或建议。

SELECT 
  positionview.equipmenttimestamp, 
  positionview.name, 
  positionview.iNumber, 
  positionview.datauserprovidername, 
  positionview.latitude, 
  positionview.longitude
FROM 
  public.positionview
WHERE positionview.outbound = false
AND positionview.referenceIdentifier is null
AND positionview.responseType = 'XYZ'
AND positionview.equipmentTimestamp >='2016-02-02 14:44:08.213'
AND positionview.equipmentTimestamp <='2016-02-05 14:44:08.213'
AND positionview.equipmentTimestamp =(
  SELECT MAX(positionview2.equipmentTimestamp)
    FROM PositionView positionview2
    WHERE positionview.iNumber = positionview2.iNumber
    AND positionview2.outbound = false
    AND positionview2.referenceIdentifier is null
    AND positionview2.responseType = 'XYZ'
    AND positionview2.equipmentTimestamp >='2016-02-02 14:44:08.213'
    AND positionview2.equipmentTimestamp <='2016-02-05 14:44:08.213');

非常感谢提前!

2 个答案:

答案 0 :(得分:2)

这种声明可以使用Postgres的distinct on()运算符完成(通常比使用标准窗口函数的等效解法更快):

SELECT distinct on (inumber)
  equipmenttimestamp, 
  name, 
  iNumber, 
  datauserprovidername, 
  latitude, 
  longitude
FROM 
  public.positionview
WHERE outbound = false
AND referenceIdentifier is null
AND responseType = 'XYZ'
AND equipmentTimestamp >='2016-02-02 14:44:08.213'
AND equipmentTimestamp <='2016-02-05 14:44:08.213'
order by inumber, equipmentTimestamp desc;

(inumber,equipmenttimestamp)上的索引可能会有所帮助

答案 1 :(得分:1)

我建议使用窗口函数:

SELECT pv.*
FROM (SELECT pv.*, MAX(pv.equipmenttimestamp) OVER (PARTITION BY pv.inumber) as maxet
      FROM public.positionview pv
      WHERE pv.outbound = false AND
            pv.referenceIdentifier is null AND
            pv.responseType = 'XYZ' AND
            pv.equipmentTimestamp >='2016-02-02 14:44:08.213' AND
            pv.equipmentTimestamp <='2016-02-05 14:44:08.213'
     ) pv
WHERE equipmenttimestamp = maxet;