Hallo liebe Gemeinde,
ich bin neu im Forum und habe ein Frage bezüglich der Codeoptimierung in Postgres. Ich habe eine Funktion dort geschrieben, welche mir aus einer großen Tabelle mit Datumsstempel und Daten folgendes macht:
- Suche alle Werte im angegebenen Zeitbereich.
- Zerteile den Zeitbereich in 1500 Werte (konstante Abstände)
- Suche nach allen Werte in jedem Zeitbereich und führe einen Mittelwert und die Standardabweichung durch
Geben das Ergebnis der Liste aus.
An und für sich funktioniert der Code, allerdings ist meine Ursprungstabelle so groß, dass eine Abfrage schon mal bis zu 30 Sekunden und länger dauern kann. Von daher wollte ich mal Fragen, ob ihr Optimierungsvorschläge dazu habt?
Die Tabelle stromzaehler gilt als Beispiel und hat folgende Spalten:
-- Table: stromzaehler
-- DROP TABLE stromzaehler;
CREATE TABLE stromzaehler
(
zeit timestamp without time zone NOT NULL,
"bezug(kwh)" double precision NOT NULL, -- Energiebezug vom Anbieter in kWh
"pv(kwh)" double precision NOT NULL, -- Energiebezug zum Anbieter in kWh
leistung double precision NOT NULL -- Aktuelle Leistung in W (-:zum Anbieter, +:vom Anbieter)
)
WITH (
OIDS=FALSE
);
ALTER TABLE stromzaehler
OWNER TO pi;
COMMENT ON COLUMN stromzaehler."bezug(kwh)" IS 'Energiebezug vom Anbieter in kWh';
COMMENT ON COLUMN stromzaehler."pv(kwh)" IS 'Energiebezug zum Anbieter in kWh';
COMMENT ON COLUMN stromzaehler.leistung IS 'Aktuelle Leistung in W (-:zum Anbieter, +:vom Anbieter)';
-- Index: index_zeit
-- DROP INDEX index_zeit;
CREATE INDEX index_zeit
ON stromzaehler
USING btree
(zeit);
Hier der aktuelle Code:
CREATE OR REPLACE FUNCTION getgraph(
IN t1 text,
IN t2 text)
RETURNS TABLE(datum timestamp without time zone, avg1 double precision, sigma double precision) AS
$BODY$
SELECT t1::timestamp + T * ((SELECT ( DATE_PART('day', t2::timestamp - t1::timestamp) * 24*60*60 +
DATE_PART('hour', t2::timestamp - t1::timestamp) * 60*60 +
DATE_PART('minute', t2::timestamp - t1::timestamp) * 60 +
DATE_PART('second', t2::timestamp - t1::timestamp) ) /1500) || ' seconds')::interval, Q.power, Q.sigma FROM
(SELECT round(( DATE_PART('day', stromzaehler.zeit::timestamp - t1::timestamp) * 24*60*60 +
DATE_PART('hour', stromzaehler.zeit::timestamp - t1::timestamp) * 60*60 +
DATE_PART('minute', stromzaehler.zeit::timestamp - t1::timestamp) * 60 +
DATE_PART('second', stromzaehler.zeit::timestamp - t1::timestamp) )/(SELECT ( DATE_PART('day', t2::timestamp - t1::timestamp) * 24*60*60 +
DATE_PART('hour', t2::timestamp - t1::timestamp) * 60*60 +
DATE_PART('minute', t2::timestamp - t1::timestamp) * 60 +
DATE_PART('second', t2::timestamp - t1::timestamp) ) /1500)) AS T, avg(stromzaehler.leistung) as power, stddev(stromzaehler.leistung) as sigma FROM stromzaehler WHERE stromzaehler.zeit::timestamp between t1::timestamp and t2::timestamp group by T ORDER BY T) AS Q;
$BODY$
LANGUAGE sql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION getgraph(text, text)
OWNER TO pi;
COMMENT ON FUNCTION getgraph(text, text) IS 'Die Funktion zerteilt alle Zeilen in der Tabelle stromzähler in maximal 1500 Teilstücke und verteilt die Spalten (mittels der Mittelwerte des Zeitintervals) in diese Intervalle.
SELECT getgraph('2019-09-01', '2019-09-03');';
Ach und ich hätte noch eine zweite Frage dazu:
Wie kann man der Funktion zum Einen die Tabelle stromzaehler und zum Anderen die zu nutzende Wertespalte dynamisch übergeben. Ich konnte das nicht mit dem code:
stromzaehler.zeit::timestamp
usw verbinden.
Danke schon mal im voraus