diff options
author | root <root@frank.tg14.gathering.org> | 2014-04-17 22:20:21 +0200 |
---|---|---|
committer | root <root@frank.tg14.gathering.org> | 2014-04-17 22:20:21 +0200 |
commit | c7ba101d90a5c49167b3355a5a3b0c629964b9b1 (patch) | |
tree | ffae85c1939b5b65475c6907dade0d523701ebda | |
parent | 3f1a385add6aad80cb7ad1237b643f1cd44d9915 (diff) |
Optimize get_current_datarate() with some new PostgreSQL 9.x stuff.
-rw-r--r-- | sql/nms.sql | 92 |
1 files changed, 23 insertions, 69 deletions
diff --git a/sql/nms.sql b/sql/nms.sql index 6af4e2a..631fe13 100644 --- a/sql/nms.sql +++ b/sql/nms.sql @@ -91,76 +91,30 @@ ALTER FUNCTION public.add_new_element(sample_state, sample) OWNER TO postgres; -- Name: get_current_datarate(); Type: FUNCTION; Schema: public; Owner: nms -- -CREATE FUNCTION get_current_datarate() RETURNS SETOF datarate - LANGUAGE plpgsql +CREATE OR REPLACE FUNCTION get_current_datarate() RETURNS SETOF datarate + LANGUAGE sql AS $$ -DECLARE - num_entries INTEGER; - poll polls; - first_poll polls; - last_poll polls; - timediff float; - ret datarate; -BEGIN - num_entries := 0; - last_poll.switch := -1; - - FOR poll IN select * from polls where time >= now() - '15 minutes'::interval and time < now() and official_port order by switch,port,time LOOP - IF poll.switch <> last_poll.switch OR poll.port <> last_poll.port THEN - IF num_entries >= 2 THEN - timediff := EXTRACT(epoch from last_poll.time - first_poll.time); - ret.switch := last_poll.switch; - ret.port := last_poll.port; - - IF last_poll.bytes_in >= first_poll.bytes_in AND last_poll.bytes_out >= first_poll.bytes_out THEN - ret.bytes_in := (last_poll.bytes_in - first_poll.bytes_in) / timediff; - ret.bytes_out := (last_poll.bytes_out - first_poll.bytes_out) / timediff; - ret.last_poll_time := last_poll.time; - return next ret; - END IF; - END IF; - num_entries := 0; - ELSE - -- reset if we have wraparound - IF last_poll.bytes_in < first_poll.bytes_in OR - last_poll.bytes_out < first_poll.bytes_out THEN - num_entries := 0; - END IF; - END IF; - - num_entries := num_entries + 1; - IF num_entries = 1 THEN - first_poll.switch := poll.switch; - first_poll.port := poll.port; - first_poll.time := poll.time; - first_poll.bytes_in := poll.bytes_in; - first_poll.bytes_out := poll.bytes_out; - END IF; - - last_poll.switch := poll.switch; - last_poll.port := poll.port; - last_poll.time := poll.time; - last_poll.bytes_in := poll.bytes_in; - last_poll.bytes_out := poll.bytes_out; - END LOOP; - - -- last - IF num_entries >= 2 THEN - timediff := EXTRACT(epoch from last_poll.time - first_poll.time); - ret.switch := last_poll.switch; - ret.port := last_poll.port; - - IF last_poll.bytes_in >= first_poll.bytes_in AND - last_poll.bytes_out >= first_poll.bytes_out THEN - ret.bytes_in := (last_poll.bytes_in - first_poll.bytes_in) / timediff; - ret.bytes_out := (last_poll.bytes_out - first_poll.bytes_out) / timediff; - ret.last_poll_time := last_poll.time; - return next ret; - END IF; - END IF; - - RETURN; -END; + SELECT switch,port, + (bytes_out[1] - bytes_out[2]) / EXTRACT(EPOCH FROM (time[1] - time[2])) AS bytes_out, + (bytes_in[1] - bytes_in[2]) / EXTRACT(EPOCH FROM (time[1] - time[2])) AS bytes_in, + time[1] AS last_poll_time + FROM ( + SELECT switch,port, + ARRAY_AGG(time) AS time, + ARRAY_AGG(bytes_in) AS bytes_in, + ARRAY_AGG(bytes_out) AS bytes_out + FROM ( + SELECT *,rank() OVER (PARTITION BY switch,port ORDER BY time DESC) AS poll_num + FROM polls WHERE time BETWEEN (now() - interval '5 minutes') AND now() + AND official_port + ) t1 + WHERE poll_num <= 2 + GROUP BY switch,port + ) t2 + WHERE + time[2] IS NOT NULL + AND bytes_out[1] >= bytes_out[2] + AND bytes_in[1] >= bytes_in[2]; $$; |