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秒。
如何优化它以减少执行时间?
答案 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_number
中vehicles
的相对较少的不同值,您可以进一步优化。您的问题中没有足够的信息。