。我有包含设备功耗值的表,我需要计算给定时间跨度的功耗并返回10个最耗电的设备。我已生成192个设备和7742208个测量记录(每个记录为40324)。这大约是设备在一个月内会产生多少记录。
对于如此大量的数据,我当前的查询要花40多个秒才能执行,这太长了,因为时间跨度,设备和测量的数量可能更高。我是否应该尝试使用不同于lag()OVER
PARTITION的方法来解决此问题,还可以进行其他哪些优化?我非常感谢代码示例的建议。
PostgreSQL 9.4版
用示例值查询:
SELECT
t.device_id,
sum(len_y*(extract(epoch from len_x))) AS total_consumption
FROM (
SELECT
m.id,
m.device_id,
m.power_total,
m.created_at,
m.power_total+lag(m.power_total) OVER (
PARTITION BY device_id
ORDER BY m.created_at
) AS len_y,
m.created_at-lag(m.created_at) OVER (
PARTITION BY device_id
ORDER BY m.created_at
) AS len_x
FROM
measurements AS m
WHERE m.created_at BETWEEN '2015-07-30 13:05:24.403552+00'::timestamp
AND '2015-08-27 12:34:59.826837+00'::timestamp
) AS t
GROUP BY t.device_id
ORDER BY total_consumption
DESC LIMIT 10;
表信息:
Column | Type | Modifiers
--------------+--------------------------+----------------------------------------------------------
id | integer | not null default nextval('measurements_id_seq'::regclass)
created_at | timestamp with time zone | default timezone('utc'::text, now())
power_total | real |
device_id | integer | not null
Indexes:
"measurements_pkey" PRIMARY KEY, btree (id)
"measurements_device_id_idx" btree (device_id)
"measurements_created_at_idx" btree (created_at)
Foreign-key constraints:
"measurements_device_id_fkey" FOREIGN KEY (device_id) REFERENCES devices(id)
查询计划:
Limit (cost=1317403.25..1317403.27 rows=10 width=24) (actual time=41077.091..41077.094 rows=10 loops=1)
-> Sort (cost=1317403.25..1317403.73 rows=192 width=24) (actual time=41077.089..41077.092 rows=10 loops=1)
Sort Key: (sum((((m.power_total + lag(m.power_total) OVER (?))) * date_part('epoch'::text, ((m.created_at - lag(m.created_at) OVER (?)))))))
Sort Method: top-N heapsort Memory: 25kB
-> GroupAggregate (cost=1041700.67..1317399.10 rows=192 width=24) (actual time=25361.013..41076.562 rows=192 loops=1)
Group Key: m.device_id
-> WindowAgg (cost=1041700.67..1201314.44 rows=5804137 width=20) (actual time=25291.797..37839.727 rows=7742208 loops=1)
-> Sort (cost=1041700.67..1056211.02 rows=5804137 width=20) (actual time=25291.746..30699.993 rows=7742208 loops=1)
Sort Key: m.device_id, m.created_at
Sort Method: external merge Disk: 257344kB
-> Seq Scan on measurements m (cost=0.00..151582.05 rows=5804137 width=20) (actual time=0.333..5112.851 rows=7742208 loops=1)
Filter: ((created_at >= '2015-07-30 13:05:24.403552'::timestamp without time zone) AND (created_at <= '2015-08-27 12:34:59.826837'::timestamp without time zone))
Planning time: 0.351 ms
Execution time: 41114.883 ms
查询以生成测试表和数据:
CREATE TABLE measurements (
id serial primary key,
device_id integer,
power_total real,
created_at timestamp
);
INSERT INTO measurements(
device_id,
created_at,
power_total
)
SELECT
device_id,
now() + (i * interval '1 minute'),
random()*(50-1)+1
FROM (
SELECT
DISTINCT(device_id),
generate_series(0,10) AS i
FROM (
SELECT
generate_series(1,5) AS device_id
) AS dev_ids
) AS gen_table;
我将尝试将部分计算移至行插入阶段。
添加新列:
alter table measurements add consumption real;
更新列:
with m1 as (
select
id, power_total, created_at,
lag(power_total) over (partition by device_id order by created_at) prev_power_total,
lag(created_at) over (partition by device_id order by created_at) prev_created_at
from measurements
)
update measurements m2
set consumption =
(m1.power_total+ m1.prev_power_total)*
extract(epoch from m1.created_at- m1.prev_created_at)
from m1
where m2.id = m1.id;
创建触发器:
create or replace function before_insert_on_measurements()
returns trigger language plpgsql
as $$
declare
rec record;
begin
select power_total, created_at into rec
from measurements
where device_id = new.device_id
order by created_at desc
limit 1;
new.consumption:=
(new.power_total+ rec.power_total)*
extract(epoch from new.created_at- rec.created_at);
return new;
end $$;
create trigger before_insert_on_measurements
before insert on measurements
for each row execute procedure before_insert_on_measurements();
查询:
select device_id, sum(consumption) total_consumption
from measurements
-- where conditions
group by 1
order by 1
我有一份flink工作,需要在1小时内重复删除收到的记录。重复数据消除后,我需要收集所有这些重复数据消除的文档,并进行一些聚合,如计数,然后生成目标主题。 现在,由于我只需要收集那些重复数据消除的文档,所以可能不需要等待1小时。我如何避免仅为收集这些文档而设置1个小时的窗口,但一旦收集到这些文档,就继续进行聚合。 因此,资源会占用内存,检查点大小也在增加,这是我想要避免的。 水印策略: 如有任何建
问题内容: 我有一个查询,使用带通配符的“ like”来搜索客户端。例如: 它还可以在“ where”子句中使用较少的参数,例如: 谁能说出优化这种查询性能的最佳方法是什么?也许我需要创建一个索引?该表在生产中最多可以有1000K条记录。 问题答案: 要在模式具有表单的位置上做很多事情,您需要查找SQL Server的全文本索引功能,并使用代替。照原样,您正在执行全表扫描,因为普通索引对搜索以通配
问题内容: 我有一个涉及Postgresql数据库的任务。我对SQL不太有经验。 我有一张桌子,上面有每周贸易产品的营业额。 对于每周,提供以下信息:产品,周数,每周营业额(可能是正数,也可能是负数,具体取决于天气是购买还是出售了更多产品)。我已经添加了一个列,每个星期都有期末余额。我在表中的第一周所有产品的期末余额(week_number= 0),而其他所有周均为“ null”。下面提供了一些示
问题内容: 在这里很难说出要问什么。这个问题是模棱两可,含糊不清,不完整,过于宽泛或夸张的,不能以目前的形式合理地回答。如需帮助澄清此问题以便可以重新打开, 请访问帮助中心。 8年前关闭。 有一个查询运行得比我想要的慢,但是我无法共享详细信息。该查询已经返回了正确的结果,并且已经对其进行了重构,但是我无法使其足够快地运行。谓词在可能的情况下已经是可Sarg- able 的。它已经正确地使用了联接,
问题内容: 每当用户接近文档顶部时,我都会尝试向下滚动100px。 当用户接近文档顶部时,我执行了该函数,但是.scrollTo函数不起作用。 我在之前和之后放置了一个警报,以检查它实际上是否是阻止该行的线路,并且只有第一个警报响起,这是代码: 我知道我的jquery页面链接正确,因为我在整个过程中都使用了许多其他jquery函数,而且它们都可以正常工作。我也尝试过从上方删除“ px”,但似乎没有
我在Scala中查看幻灯片函数中的Spark。
我有一个这样的查询,其中join~6000个值 多值查询的查询计划: 我使用PosgreSQL 10.8.0。有没有可能加快这个查询的速度? 我尝试用递归替换DISTINCT: 但结果更慢。 哈希连接(成本=418.67..21807.22行=3000宽度=24)(实际时间=16.804..10843.174行=5991循环=1)哈希Cond:(t.user_id="VALUES"。专栏1)缓冲区
问题内容: 从EMPLOYEE表中,我想对记录的数量(雇用的雇员)进行分组,并且还需要每天运行的TOTAL。输入的格式如下: 所需的输出: 每天的分组没有问题: 问题 :如何使用窗口功能获得总计(在最后一栏中) 问题答案: http://sqlfiddle.com/#!4/4bd36/9