我有这个物化视图:
Materialized view "public.kwh_tag"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
-------------+------------------+-----------+----------+---------+---------+--------------+-------------
timest | date | | | | plain | |
Zählerstand | double precision | | | | plain | |
kWh | double precision | | | | plain | |
Indexes:
"kwh_tag_timest_idx" UNIQUE, btree (timest)
View definition:
SELECT s.timest::date AS timest,
s.kwh_180 AS "Zählerstand",
s.kwh_180 - lag(s.kwh_180, 1) OVER (ORDER BY s.timest) AS "kWh"
FROM ( SELECT DISTINCT ON ((smartmeter.timest::date)) smartmeter.timest,
smartmeter.kwh_180
FROM smartmeter
ORDER BY (smartmeter.timest::date) DESC, smartmeter.timest DESC) s;
输出:
2023-06-10 | 35965.0285 | 22.8133000000016
2023-06-11 | 35985.919 | 20.8905000000013
2023-06-12 | 36012.7307 | 26.8116999999984
2023-06-13 | 36030.2164 | 17.4856999999975
原因是,这个查询需要很多时间,因为表smartmeter
每秒存储一次数据(如果设备需要更长的时间,则为2)。
REFRESH MATERIALIZED VIEW
Time: 94290.866 ms (01:34.291)
然而,每天刷新视图也需要更多的时间,有没有更好的方法来处理这个问题?
我尝试使用CONCURRENTLY
,但这需要更长的时间,尽管只有一点点:
REFRESH MATERIALIZED VIEW CONCURRENTLY kwh_tag;
REFRESH MATERIALIZED VIEW
Time: 111461.192 ms (01:51.461)
理想情况下,只需要计算最近的一天,因为旧的值不会改变。我可以在postgres之外这样做,然后把它保存回来,但是一个in-postgres的解决方案会更好。
2条答案
按热度按时间v2g6jxz61#
这种情况的一个替代方案是将timescaledb扩展与continuous aggregates特性一起使用。
您可以创建一个仅在新数据中运行的连续聚合策略,因为它使用水印来了解最新运行的数据。
vxf3dgd42#
您可以创建分区表,而不是实体化视图。每个分区用于特定时间范围内的值。每天,您都会使用
TRUNCATE
和INSERT INTO ... SELECT ...
来重建最新的分区。