I'd like to compare two functions in pgAdmin's SQL editor. Here's the script. However, when I run it, seems the start_time and end_time have the same value no matter how many iterations. (But, the Query returned successfully with no result in nnn ms. message does go higher with every increase in the loop size.) Why?
DO
$$
DECLARE
start_time timestamp;
end_time timestamp;
diff interval;
BEGIN
SELECT now() INTO start_time;
FOR i IN 1..1000 LOOP
--PERFORM uuid_generate_v1mc();
PERFORM id_generator();
END LOOP;
SELECT now() INTO end_time;
SELECT end_time - start_time INTO diff;
RAISE NOTICE '%', start_time;
RAISE NOTICE '%', end_time;
RAISE NOTICE '%', diff;
END
$$
From the manual
Since these functions [CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE] return the start time of the current transaction, their values do not change during the transaction.
And then further down:
transaction_timestamp() is equivalent to CURRENT_TIMESTAMP, but is named to clearly reflect what it returns. statement_timestamp() returns the start time of the current statement (more specifically, the time of receipt of the latest command message from the client). statement_timestamp() and transaction_timestamp() return the same value during the first command of a transaction, but might differ during subsequent commands. clock_timestamp() returns the actual current time, and therefore its value changes even within a single SQL command
So you probably want to use clock_timestamp()
Related
I want to see how long a loop iteration takes inside a DO block in postgres. The basic layout is as follows:
DO $$
declare v_time timestamptz;
declare i record;
begin
for i in select generate_series(1, 5) t
loop
select current_timestamp into v_time;
perform pg_sleep(i.t);
-- something done here (pg_sleep to ensure some time passes)
raise notice '%', v_time - (select current_timestamp);
-- expect negative interval from RAISE.
end loop;
end; $$;
However, when I run this (have tried on Postgres 13 and 9), I get an interval of 0S returned:
NOTICE: 00:00:00
NOTICE: 00:00:00
NOTICE: 00:00:00
NOTICE: 00:00:00
NOTICE: 00:00:00
DO
Query returned successfully in 15 secs 389 msec.
I have done this previously and have never run into this issue before, so I guess my question is "what am I doing wrong this time?" instead of "why is postgres behaving unexpectedly?"
current_timestamp is defined to be:
the start time of the current transaction, their values do not change during the transaction
you probably want to use clock_timestamp() instead which returns a value that changes within a transaction, see the link above for a more complete description.
I just want to know if i can call a procedure automatically when something happens. In particular, i would want to call a function that deletes records from a table when now() timestamp is one month past the timestamp atribute of the record. Something like
create or replace procedure eliminate_when_time_past()
as $$
begin
if (now() is one month past the record timestamp) then
delete from preƱadas where hierro = ...
end if;
end;
$$
language plpgsql
Is it possible?
So, i have a couple of functions inside my db.
One function needs to run when the data in a specific table is older than 5 minutes.
I've tried doing it with:
PERFORM case when now() - '5 minutes'::interval > (select end_time from x order by end_route desc limit 1) then update_x() else null end;
When i run the command as a regular select query, it runs OK. But when i put that inside another function (The one being called, returns updated table that is no older than 5 minutes), it never runs. Also, if i just put update_x(), then it runs OK (but every time the function is called).
Does anyone have any idea on how i could fix this?
One idea is to just set a cron to run the function every 5 mins independently, but i'd rather the server is idle since the function is quite resource intensive, and it doesn't get called that often.
I'm on version 8.4(Due to my ISP, so can't change, though i am considering moving to VPS, so if this is something that would work on 9.5 and newer, i can wait).
The function now() gives the start time of the current transaction and is invariable inside it. Use clock_timestamp(), example:
do $$
begin
for i in 1..3 loop
perform pg_sleep(1);
raise notice 'now(): % clock_timestamp(): %', now(), clock_timestamp();
end loop;
end $$;
NOTICE: now(): 2017-12-06 10:22:40.422683+01 clock_timestamp(): 2017-12-06 10:22:41.437099+01
NOTICE: now(): 2017-12-06 10:22:40.422683+01 clock_timestamp(): 2017-12-06 10:22:42.452456+01
NOTICE: now(): 2017-12-06 10:22:40.422683+01 clock_timestamp(): 2017-12-06 10:22:43.468124+01
Per the documentation:
clock_timestamp() returns the actual current time, and therefore its value changes even within a single SQL command (...)
now() is a traditional PostgreSQL equivalent to transaction_timestamp().
I'm not sure why, but once i moved the boolean up one level it started working.
So now instead of having perform case query inside function, i'm sending boolean to the function, and performing the check in a view above this function.
CREATE VIEW x_view AS select * from get_x((clock_timestamp() - '5 minutes'::interval)::timestamp > (select end_route from gps_skole2 order by end_route desc limit 1));
And inside the function:
PERFORM case when $1 then update_x() else null end;
I need, in a plpgsql script, to get the execution time of the last query in a variable for several purposes (calculation, display and storage), so the psql \timing option is not what I look for because I can't manipulate the result time. Do you know if there is anything like the "get diagnostics" command, but for execution time (or work around) ?:
get diagnostics my_var := EXECUTION_TIME;
I couldn't find anything else than row_count and result_oid...
You can compare clock_timestamp() before and after the query:
do $$
declare t timestamptz := clock_timestamp();
begin
perform pg_sleep(random());
raise notice 'time spent=%', clock_timestamp() - t;
end
$$ language plpgsql;
Sample result:
NOTICE: time spent=00:00:00.59173
do $$
declare
tm1 timestamp without time zone;
tm2 timestamp without time zone;
begin
select localtimestamp(0) into tm1;
for i in 1..200000000 loop
--just waiting several second
end loop;
select localtimestamp(0) into tm2;
raise notice '% ; %', tm1, tm2;
end;
$$ language plpgsql
Why gives this procedure same values for tm1 and tm2 ?
Is not executed this code step by step?
From the manual
These SQL-standard functions all return values based on the start time of the current transaction [...] Since these functions return the start time of the current transaction, their values do not change during the transaction. This is considered a feature: the intent is to allow a single transaction to have a consistent notion of the "current" time, so that multiple modifications within the same transaction bear the same time stamp
(Emphasis mine)
You probably want clock_timestamp()