Postgresql

昂貴子查詢的優化

  • March 12, 2014

以下查詢獲取<> 0與指定單位關聯的最後一個報告(緯度和經度和秒所在的位置):

SELECT 
   reports.* 
FROM
   reports 
   INNER JOIN 
       units 
       ON units.id = reports.unit_id 
WHERE 
   reports.unit_id IN (1111, 1112, 1113) 
   AND 
   (
       reports.id = 
       (
           SELECT reports.id 
           FROM reports
           WHERE reports.unit_id = units.id
           AND
           reports.time_secs != 0
           AND 
           reports.latitude != 0.0
           AND
           reports.longitude != 0.0
           ORDER BY time desc
           LIMIT 1
       )
   )

此查詢需要幾分鐘才能執行,我想知道是否可以對其進行優化。

這可以通過以下方式變得更加簡單和快捷DISTINCT ON

SELECT DISTINCT ON (r.unit_id)
      r.* 
FROM   reports r
JOIN   units   u ON u.id = r.unit_id 
WHERE  r.unit_id IN (1111, 1112, 1113) 
AND    r.time_secs <> 0
AND    r.latitude  <> 0.0
AND    r.longitude <> 0.0
ORDER  BY r.unit_id, r.time DESC;

這些相關答案中的更多解釋:

如何有效地獲取“最新的相應行”?

在每個 GROUP BY 組中選擇第一行?(關於 SO)

次要細節:“不等於”的標準 SQL 運算符是<>. 使用它而不是!=(在 Postgres 中也被接受)。

在此查詢中加入表的唯一可能目的**units**是驗證是否存在一個或多個相關行。如果reports.unit_id被外鍵綁定unit.id(如命名所暗示的那樣),則可以保證引用完整性,並且您可以unit從查詢中完全刪除表。只需添加:unit_id IS NOT NULL

SELECT DISTINCT ON (unit_id) * 
FROM   reports
WHERE  unit_id IN (1111, 1112, 1113) 
AND    time_secs <> 0
AND    latitude  <> 0.0
AND    longitude <> 0.0
AND    unit_id IS NOT NULL
ORDER  BY unit_id, time DESC;

引用自:https://dba.stackexchange.com/questions/60494