diff --git a/internal/server/postgres/dataserverimpl.go b/internal/server/postgres/dataserverimpl.go index a1b5757..aa88139 100644 --- a/internal/server/postgres/dataserverimpl.go +++ b/internal/server/postgres/dataserverimpl.go @@ -1021,7 +1021,7 @@ func (s *DataPlatformDataServiceServerImpl) GetForecastAtTimestamp( Latitude: value.Latitude, Longitude: value.Longitude, }, - Metadata: value.Metadata, + Metadata: value.Metadata, InitializationTimestampUtc: timestamppb.New(value.InitTimeUtc.Time), CreatedTimestampUtc: timestamppb.New(value.CreatedAtUtc.Time), } diff --git a/internal/server/postgres/sql/queries/observations.sql b/internal/server/postgres/sql/queries/observations.sql index c9fd58d..3e36853 100644 --- a/internal/server/postgres/sql/queries/observations.sql +++ b/internal/server/postgres/sql/queries/observations.sql @@ -83,36 +83,27 @@ WHERE * observer. The value is returned as a 16-bit integer, with 0 representing 0% * and 30000 representing 100% of capacity. */ -WITH ranked_observations AS ( - SELECT - og.geometry_uuid, - og.source_type_id, - og.observation_timestamp_utc, - og.value_sip, - sh.capacity_limit_sip, - sh.capacity_watts, - ROW_NUMBER() OVER ( - PARTITION BY og.geometry_uuid, og.source_type_id, o.observer_uuid - ORDER BY og.observation_timestamp_utc DESC - ) AS rn - FROM obs.observed_generation_values AS og - INNER JOIN loc.sources_mv AS sh USING (geometry_uuid, source_type_id) - INNER JOIN obs.observers AS o USING (observer_uuid) - WHERE - og.geometry_uuid = ANY(sqlc.arg(geometry_uuids)::UUID []) - AND og.source_type_id = $1 - AND o.observer_name = LOWER(sqlc.arg(observer_name)::TEXT) - AND sh.sys_period @> og.observation_timestamp_utc - AND og.observation_timestamp_utc <= sqlc.arg(pivot_time_utc)::TIMESTAMP -) -SELECT - geometry_uuid, - source_type_id, - observation_timestamp_utc, - value_sip, - capacity_watts -FROM ranked_observations -WHERE rn = 1; +SELECT DISTINCT ON (og.geometry_uuid, og.source_type_id, o.observer_uuid) + og.geometry_uuid, + og.source_type_id, + og.observation_timestamp_utc, + og.value_sip, + sh.capacity_limit_sip, + sh.capacity_watts +FROM obs.observed_generation_values AS og + INNER JOIN loc.sources_mv AS sh USING (geometry_uuid, source_type_id) + INNER JOIN obs.observers AS o USING (observer_uuid) +WHERE + og.geometry_uuid = ANY(sqlc.arg(geometry_uuids)::UUID []) + AND og.source_type_id = $1 + AND o.observer_name = LOWER(sqlc.arg(observer_name)::TEXT) + AND sh.sys_period @> og.observation_timestamp_utc + AND og.observation_timestamp_utc <= sqlc.arg(pivot_time_utc)::TIMESTAMP +ORDER BY + og.geometry_uuid ASC, + og.source_type_id ASC, + o.observer_uuid ASC, + og.observation_timestamp_utc DESC; -- name: ListObservationsAtTimeForLocations :many /* ListObservationsAtTimeForLocations retrieves observed generation values as percentages diff --git a/internal/server/postgres/sql/queries/predictions.sql b/internal/server/postgres/sql/queries/predictions.sql index 28a3ebe..ad13c8a 100644 --- a/internal/server/postgres/sql/queries/predictions.sql +++ b/internal/server/postgres/sql/queries/predictions.sql @@ -103,7 +103,7 @@ WHERE forecast_uuid = $1; WITH forecasts_to_delete AS ( SELECT forecast_uuid FROM pred.forecasts AS f WHERE f.forecast_uuid >= UUIDV7_BOUNDARY(sqlc.arg(init_timestamp)::TIMESTAMP) - AND f.forecast_uuid < UUIDV7_BOUNDARY(sqlc.arg(init_timestamp)::TIMESTAMP + INTERVAL '1 second') + AND f.forecast_uuid < UUIDV7_BOUNDARY(sqlc.arg(init_timestamp)::TIMESTAMP + INTERVAL '1 millisecond') AND f.geometry_uuid = $1 AND f.source_type_id = $2 AND f.forecaster_id = $3 @@ -303,8 +303,12 @@ ORDER BY * * Note that the 3 day intervals are due to our forecasts only going out to 2 days. * If we increase that horizon, these will need to be increased. + * Unnesting the locations to begin with helps partitionwise querying. */ -WITH relevant_forecasts AS ( +WITH target_locations AS ( + SELECT UNNEST(sqlc.arg(geometry_uuids)::UUID []) AS geometry_uuid +), +relevant_forecasts AS ( SELECT DISTINCT ON (f.geometry_uuid) f.forecast_uuid, f.geometry_uuid, @@ -312,10 +316,9 @@ WITH relevant_forecasts AS ( f.created_at_utc, UUIDV7_EXTRACT_TIMESTAMP(f.forecast_uuid)::TIMESTAMP AS init_time_utc, f.metadata - FROM pred.forecasts AS f - WHERE - f.geometry_uuid = ANY(sqlc.arg(geometry_uuids)::UUID []) - AND f.source_type_id = $1 + FROM target_locations AS tl + INNER JOIN pred.forecasts AS f ON tl.geometry_uuid = f.geometry_uuid + WHERE f.source_type_id = $1 AND f.forecaster_id = $2 AND f.forecast_uuid >= UUIDV7_BOUNDARY( COALESCE( @@ -393,13 +396,14 @@ WITH desired_init_times AS ( relevant_forecasts AS ( SELECT f.forecast_uuid, - UUIDV7_EXTRACT_TIMESTAMP(f.forecast_uuid)::TIMESTAMP AS init_time_utc, f.source_type_id, f.geometry_uuid, - f.forecaster_id - FROM pred.forecasts AS f - INNER JOIN desired_init_times AS dit - ON UUIDV7_EXTRACT_TIMESTAMP(f.forecast_uuid)::TIMESTAMP = dit.init_time_utc + f.forecaster_id, + dit.init_time_utc + FROM desired_init_times AS dit + INNER JOIN pred.forecasts AS f + ON f.forecast_uuid >= UUIDV7_BOUNDARY(dit.init_time_utc) + AND f.forecast_uuid < UUIDV7_BOUNDARY(dit.init_time_utc + INTERVAL '1 millisecond') WHERE f.geometry_uuid = ANY(sqlc.arg(geometry_uuids)::UUID []) AND f.source_type_id = $1 AND f.forecaster_id = $2