add batch remove batch split batch comment selection show hidden batches hide batch highlight batch
db<>fiddle
donate feedback about
By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
Help with an interesting Postgres question: Why isn't an Index Only Scan used on a partition accessed via the parent table?.
create extension if not exists "uuid-ossp";
create type metric_enum as enum('distance','speed','elevation');
create table example_input(
asset_id uuid
,timestamp timestamp(0)
,metric_name metric_enum
,metric_value int);
insert into example_input values
('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:14','distance',100)
,('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:14','speed',60)
,('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:14','elevation',15)
,('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:14','distance',120)
,('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:14','speed',80)
,('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:19','distance',140)
,('07536cba-6e00-4b8a-be02-9509228f4bb0','2024-12-16 17:43:19','elevation',20)
returning *;
CREATE EXTENSION
CREATE TYPE
CREATE TABLE
asset_id timestamp metric_name metric_value
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 distance 100
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 speed 60
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 elevation 15
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 distance 120
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 speed 80
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:19 distance 140
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:19 elevation 20
INSERT 0 7
select*,uuid_generate_v3(asset_id,concat(timestamp,row_number()over w))as update_id
from example_input
window w as(partition by asset_id,timestamp,metric_name
order by ctid)
order by asset_id, timestamp, update_id, metric_name;
asset_id timestamp metric_name metric_value update_id
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 distance 100 7e88679b-5038-3124-b0e6-a4ed16316ba4
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 speed 60 7e88679b-5038-3124-b0e6-a4ed16316ba4
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 elevation 15 7e88679b-5038-3124-b0e6-a4ed16316ba4
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 distance 120 d1ca0905-7fa1-3f8c-9284-2d615bdaacd3
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 speed 80 d1ca0905-7fa1-3f8c-9284-2d615bdaacd3
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:19 distance 140 40e25bd6-55eb-34cd-a8c5-262cd9d8987b
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:19 elevation 20 40e25bd6-55eb-34cd-a8c5-262cd9d8987b
SELECT 7
alter table example_input add column update_id uuid;

update example_input as a
set update_id=uuid_generate_v3(asset_id,concat(timestamp,(
select row_number()over(order by ctid)
from example_input as c
where a.asset_id=c.asset_id
and a.timestamp=c.timestamp
and a.metric_name=c.metric_name
order by c.ctid<>a.ctid limit 1)))
returning *;
ALTER TABLE
asset_id timestamp metric_name metric_value update_id
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 distance 100 7e88679b-5038-3124-b0e6-a4ed16316ba4
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 speed 60 7e88679b-5038-3124-b0e6-a4ed16316ba4
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 elevation 15 7e88679b-5038-3124-b0e6-a4ed16316ba4
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 distance 120 d1ca0905-7fa1-3f8c-9284-2d615bdaacd3
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:14 speed 80 d1ca0905-7fa1-3f8c-9284-2d615bdaacd3
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:19 distance 140 40e25bd6-55eb-34cd-a8c5-262cd9d8987b
07536cba-6e00-4b8a-be02-9509228f4bb0 2024-12-16 17:43:19 elevation 20 40e25bd6-55eb-34cd-a8c5-262cd9d8987b
UPDATE 7
--performance on 200k rows
select setseed(.42);

insert into example_input
select uuid_generate_v3(uuid_nil(),(random()*1e3)::int::text)
,(now()-random()*'70 seconds'::interval)::timestamp(0)
,(array['distance','speed','elevation']::metric_enum[])[1+(random()*2)::int]
,(random()*100)::int
from generate_series(1,2e5);
setseed
SELECT 1
INSERT 0 200000
alter table example_input
drop column if exists update_id
,drop column if exists id
,add column update_id uuid
,add column id serial;
create index idx1 on example_input(asset_id,timestamp,metric_name,id)
with(fillfactor=100);
ALTER TABLE
CREATE INDEX
vacuum analyze example_input;
VACUUM
cluster example_input using idx1;
CLUSTER
explain analyze verbose
select*,uuid_generate_v3(asset_id,concat(timestamp,row_number()over w))as update_id
from example_input
window w as(partition by asset_id,timestamp,metric_name
order by ctid);
QUERY PLAN
WindowAgg (cost=1.42..28567.34 rows=200007 width=74) (actual time=0.196..843.894 rows=200007 loops=1)
  Output: asset_id, "timestamp", metric_name, metric_value, update_id, id, uuid_generate_v3(asset_id, concat("timestamp", row_number() OVER (?))), ctid
  -> Incremental Sort (cost=1.42..23067.14 rows=200007 width=58) (actual time=0.138..158.321 rows=200007 loops=1)
        Output: asset_id, "timestamp", metric_name, ctid, metric_value, update_id, id
        Sort Key: example_input.asset_id, example_input."timestamp", example_input.metric_name, example_input.ctid
        Presorted Key: example_input.asset_id, example_input."timestamp", example_input.metric_name
        Full-sort Groups: 6148 Sort Method: quicksort Average Memory: 27kB Peak Memory: 27kB
        -> Index Scan using idx1 on public.example_input (cost=0.42..14056.52 rows=200007 width=58) (actual time=0.062..70.343 rows=200007 loops=1)
              Output: asset_id, "timestamp", metric_name, ctid, metric_value, update_id, id
Planning Time: 0.417 ms
Execution Time: 861.788 ms
EXPLAIN
explain analyze verbose
update example_input as a
set update_id=uuid_generate_v3(asset_id,timestamp::text || (
select row_number()over(order by id)
from example_input as c
where a.asset_id=c.asset_id
and a.timestamp=c.timestamp
and a.metric_name=c.metric_name
order by c.id<>a.id limit 1));
QUERY PLAN
Update on public.example_input a (cost=0.00..1701726.50 rows=0 width=0) (actual time=6314.550..6314.552 rows=0 loops=1)
  -> Seq Scan on public.example_input a (cost=0.00..1701726.50 rows=200007 width=22) (actual time=0.098..3463.995 rows=200007 loops=1)
        Output: uuid_generate_v3(a.asset_id, ((a."timestamp")::text || ((SubPlan 1))::text)), a.ctid
        SubPlan 1
          -> Limit (cost=8.47..8.47 rows=1 width=13) (actual time=0.011..0.011 rows=1 loops=200007)
                Output: (row_number() OVER (?)), ((c.id <> a.id)), c.id
                -> Sort (cost=8.47..8.47 rows=1 width=13) (actual time=0.010..0.010 rows=1 loops=200007)
                      Output: (row_number() OVER (?)), ((c.id <> a.id)), c.id
                      Sort Key: ((c.id <> a.id))
                      Sort Method: quicksort Memory: 25kB
                      -> WindowAgg (cost=0.42..8.46 rows=1 width=13) (actual time=0.007..0.008 rows=2 loops=200007)
                            Output: row_number() OVER (?), (c.id <> a.id), c.id
                            -> Index Only Scan using idx1 on public.example_input c (cost=0.42..8.44 rows=1 width=4) (actual time=0.004..0.005 rows=2 loops=200007)
                                  Output: c.id
                                  Index Cond: ((c.asset_id = a.asset_id) AND (c."timestamp" = a."timestamp") AND (c.metric_name = a.metric_name))
                                  Heap Fetches: 518691
Planning Time: 0.457 ms
Execution Time: 6314.638 ms
EXPLAIN
select * from example_input
order by asset_id, timestamp, update_id, metric_name::metric_enum
fetch first 10 rows with ties;
asset_id timestamp metric_name metric_value update_id id
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 distance 47 1cc013d0-f9e4-376a-ae19-370a4b832d4b 170745
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 speed 77 1cc013d0-f9e4-376a-ae19-370a4b832d4b 106587
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 elevation 85 1cc013d0-f9e4-376a-ae19-370a4b832d4b 50134
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 speed 4 f17eb59b-7ae9-30a0-b682-e00859d8e5c7 124767
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 speed 30 0c723551-80c0-3477-9576-e8d0046dcf09 117999
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 distance 19 a8a2263c-02f7-3894-bfd5-e1d58f302c61 165042
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 speed 78 a8a2263c-02f7-3894-bfd5-e1d58f302c61 58158
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 elevation 2 a8a2263c-02f7-3894-bfd5-e1d58f302c61 105154
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 speed 13 fd8254c6-c9c2-3cf7-84ee-06b8f2b5a9b0 164137
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:11 distance 59 1965ec51-70cf-3842-92b1-255f673ac890 144820
SELECT 10
alter table example_input
drop column if exists update_id
,drop column if exists id;

select*,uuid_generate_v3(asset_id,concat(timestamp,(row_number()over w)))as update_id
from example_input
window w as(partition by asset_id,timestamp,metric_name
order by ctid)
order by asset_id, timestamp, update_id, metric_name::metric_enum
fetch first 10 rows with ties;
ALTER TABLE
asset_id timestamp metric_name metric_value update_id
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 distance 47 1cc013d0-f9e4-376a-ae19-370a4b832d4b
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 speed 77 1cc013d0-f9e4-376a-ae19-370a4b832d4b
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 elevation 85 1cc013d0-f9e4-376a-ae19-370a4b832d4b
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:09 speed 4 f17eb59b-7ae9-30a0-b682-e00859d8e5c7
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 speed 30 0c723551-80c0-3477-9576-e8d0046dcf09
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 distance 19 a8a2263c-02f7-3894-bfd5-e1d58f302c61
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 speed 78 a8a2263c-02f7-3894-bfd5-e1d58f302c61
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 elevation 2 a8a2263c-02f7-3894-bfd5-e1d58f302c61
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:10 speed 13 fd8254c6-c9c2-3cf7-84ee-06b8f2b5a9b0
0017c077-cbc1-3525-90b4-b505b5f8768f 2024-12-30 22:45:11 distance 59 1965ec51-70cf-3842-92b1-255f673ac890
SELECT 10