PostgreSQL查询时间

时间:2014-12-16 11:06:59

标签: sql postgresql postgresql-performance

SELECT * 
FROM vehicles t1 
WHERE (SELECT COUNT(*) FROM vehicles t2
       WHERE  t1.pump_number = t2.pump_number
          AND t1.updated_at < t2.updated_at
      ) < 4
      AND t1.updated_at >= ?

我为参数'1970-01-01 00:00:00.000000'提供?

我在vehicles表中有大约10k条记录,并且没有添加任何索引。以上查询执行大约需要10-20秒。

如何优化它以减少执行时间?

4 个答案:

答案 0 :(得分:1)

Postgres提供了很好的管理工具,它有EXPLAIN选项来查看查询执行计划。  它会给出很好的见解。这里是pgadmin的详细链接 http://www.pgadmin.org/docs/1.4/query.html

还可以在查询中使用联接,而不是使用可提高查询性能的选择

答案 1 :(得分:0)

试试这个(select和group by语句中的列需要替换为你自己的列):

SELECT
    t1.id,
    t1.updated_at,
    t1.other_columns
FROM vehicles t1 
INNER JOIN vehicles t2
ON  t1.pump_number = t2.pump_number
    AND t1.updated_at < t2.updated_at
WHERE t1.updated_at >= '1970-01-01 00:00:00.000000'
GROUP BY 
    t1.id,
    t1.updated_at,
    t1.other_columns
having count(*)< 4

在此更改之后,您可以尝试在列pump_number上添加索引以查看它是否有帮助。

答案 2 :(得分:0)

这是您的查询:

SELECT *
FROM vehicles t1
WHERE  (SELECT Count(*)
        FROM vehicles t2
        WHERE t1.pump_number = t2.pump_number AND
              t1.updated_at < t2.updated_at
       ) < 4  AND
       t1.updated_at >= ? " , "1970-01-01 00:00:00.000000")]

我首先使用窗口函数编写:

select v.*
from (select v.*, row_number() over (partition by pump_number order by updated_at) as seqnum
      from vehicles v
     ) v
where v.seqnum < 4 and t1.updated_at >= ?;

对于此查询,我建议在vehicles(pump_number, updted_at)vehicles(updated_at)上建立索引。

答案 3 :(得分:0)

要获得等效查询,请使用窗口函数 rank() ,而不是 row_number()

SELECT *
FROM  (
   SELECT *
        , rank() OVER (PARTITION BY pump_number ORDER BY updated_at DESC) AS rnk
   FROM   vehicles t1 
   ) sub
WHERE rnk < 4
AND   updated_at >= '1970-01-01 0:0';

并且必须为ORDER BY updated_at DESC,以排除同一pump_number个具有三个以上对等的行。换句话说:
&#34;根据pump_number&#34; 上的关系,获取每updated_at个最早的行 - 或更多行。

无论如何,当您阅读大部分或全部表时,索引都无济于事。

进一步优化性能

如果(pump_number, updated_at)是唯一的,或/ pump_numbervehicles的相对较少的不同值,您可以进一步优化。您的问题中没有足够的信息。