代码之家  ›  专栏  ›  技术社区  ›  dnzdlklc

PostgreSQL MAX()内部查询非常慢

  •  1
  • dnzdlklc  · 技术社区  · 8 年前

    我目前的任务是优化一些在非常大的数据集上运行的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 回复  |  直到 8 年前
        1
  •  2
  •   a_horse_with_no_name    8 年前

    这种语句可以使用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) 可能会有所帮助

        2
  •  1
  •   Gordon Linoff    8 年前

    我建议使用窗口函数:

    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;