我正在尝试使用postgresql计算一段时间内的多个平均值(每个id一个)。
我有一个有效的查询,但是非常慢。 (在我的笔记本电脑上3分钟,在服务器上30秒。。)
我想做的是计算最近X天的平均值。可能存在日期间隔(对于星期六和星期日,没有数据),但是我仍然需要最后一个X。因此,例如1month将是20天,等等。
为此,我一直使用row_number() OVER (PARTITION BY item_id ORDER BY tdate DESC)
并仅选择BETWEEN 0 AND X
(X是我需要的最大日期数)
我的完整查询是:
SELECT x.item_id AS id,avg(x.value) AS result FROM
(SELECT il.item_id, il.value, row_number() OVER (PARTITION BY
il.item_id ORDER BY il.tdate DESC) rn
FROM item_prices il) x
WHERE x.rn BETWEEN 0 AND 50 GROUP BY x.item_id order by x.item_id ASC;
正如我所说,我的问题是运行速度非常慢。我怀疑PSQL正在为每个id重新计算SELECT il.item_id, il.value, row_number() OVER (PARTITION BY il.item_id ORDER BY il.tdate DESC
,这就是为什么它这么慢的原因。
我一直在阅读有关平均水平的内容,并尝试了一些方法(this),但均未成功。
有人会知道如何使查询更快吗?
我的桌子看起来像这样:
ID,item_id,value,tdate
说明:
GroupAggregate (cost=7707688.82..8934895.66 rows=36453 width=36)
Group Key: x.item_id
-> Subquery Scan on x (cost=7707688.82..8933564.38 rows=175125 width=14)
Filter: ((x.rn >= 1) AND (x.rn <= 50))
-> WindowAgg (cost=7707688.82..8408189.14 rows=35025016 width=26)
-> Sort (cost=7707688.82..7795251.36 rows=35025016 width=18)
Sort Key: il.item_id, il.tdate DESC
-> Seq Scan on item_prices il (cost=0.00..1163862.16 rows=35025016 width=18)
答案 0 :(得分:1)
您可以尝试将以下索引添加到item_prices
表中:
CREATE INDEX idx ON item_prices (item_id, tdate, value);
这可以加快ROW_NUMBER
中发生的分区的速度,因此可以提高内部查询的性能。关于求平均值,我们无法避免触及每个item_id
范围内的每个值,因此可能没有太多可以做的事情了。
实际上,还有其他一些小的优化。您可以从内部查询中删除ORDER BY
子句,该子句毫无用处(甚至不会“坚持”):
SELECT
x.item_id AS id,
AVG(x.value) AS result
FROM
(
SELECT il.item_id, il.value,
ROW_NUMBER() OVER (PARTITION BY il.item_id ORDER BY il.tdate DESC) rn
FROM item_prices il
) x
WHERE
x.rn BETWEEN 1 AND 50 -- row number starts at 1, not 0
GROUP BY
x.item_id
ORDER BY
x.item_id;
答案 1 :(得分:1)
我想做的是计算最近X天的平均值。
这将建议:
SELECT ip.item_id AS id, avg(x.value) AS result
FROM item_prices ip
WHERE ip.tdate <= current_date AND
ip.tdate > current_date - X * interval '1 day'
GROUP BY ip.item_id;
不过,我看不出您的实际查询与您所问的问题有什么关系。