我正在使用 Postgresql。我想测试一个函数执行需要多少时间。由于该函数只需要几毫秒,我想在循环中调用它 1000 次以获得准确的数字。
MySQL 有一个 BENCHMARK() 函数来执行此操作。是否有等价物或者我必须编写一个带有循环的程序才能做到这一点?
我正在使用 Postgresql。我想测试一个函数执行需要多少时间。由于该函数只需要几毫秒,我想在循环中调用它 1000 次以获得准确的数字。
MySQL 有一个 BENCHMARK() 函数来执行此操作。是否有等价物或者我必须编写一个带有循环的程序才能做到这一点?
在 PostgreSQL 中,您通常使用以下方法执行此操作generate_series
:
SELECT my_function()
FROM generate_series(1,5000);
或者
SELECT (SELECT my_query ....)
FROM generate_series(1,5000);
在后一种情况下,您可以添加OFFSET 0
到子查询或将其包装在STRICT
SQL 函数中,以防止查询计划器提取常见条件和子条款,否则会变得聪明。
可以使用 psql 的\timing
命令 withSET log_duration = on
或 with来获得EXPLAIN (ANALYZE, BUFFERS)
时间,所有这些时间都略有不同 - 请参阅文档。简而言之,\timing
衡量时间,包括往返和向客户的价值转移。log_duration
测量服务器端执行时间。EXPLAIN (ANALYZE, BUFFERS)
测量语句执行的细节,但增加了可能会减慢它的时间开销。
编写一个带循环的程序 - 不应超过 5 分钟。
CREATE OR REPLACE FUNCTION benchmark(loop_count int,
sql_expr text, -- SQL expression
is_cache_plan boolean default true) returns interval
immutable
strict
parallel safe -- Postgres 10 or later
language plpgsql
AS
$$
BEGIN
if is_cache_plan then
EXECUTE 'select ($1) from generate_series(1, $2)' using sql_expr, loop_count;
else
FOR i IN 1..loop_count LOOP
EXECUTE 'select ($1)' using sql_expr;
END LOOP;
end if;
RETURN clock_timestamp() - now();
END
$$;
-- TESTS (parse URL)
select benchmark(
500000,
$$substring(format('https://www.domain%s.com/?aaa=1111&b[2]=3#test', (random()*1000)::int::text) from '^[^:]+://([^/]+)')$$,
true);
-- 0 years 0 mons 0 days 0 hours 0 mins 0.300638 secs
select benchmark(
500000,
$$substring(format('https://www.domain%s.com/?aaa=1111&b[2]=3#test', (random()*1000)::int::text) from '^[^:]+://([^/]+)')$$,
false);
-- 0 years 0 mons 0 days 0 hours 0 mins 6.735336 secs
-- TESTS (generate UUID)
SELECT benchmark(1000000, $$uuid_in(overlay(overlay(md5(random()::text || ':' || clock_timestamp()::text) placing '4' from 13) placing to_hex(floor(random()*(11-8+1) + 8)::int)::text from 17)::cstring)$$);
-- 0 years 0 mons 0 days 0 hours 0 mins 0.644648 secs
SELECT benchmark(1000000, $$md5(random()::text || clock_timestamp()::text)::uuid$$);
-- 0 years 0 mons 0 days 0 hours 0 mins 0.449026 secs
SELECT benchmark(1000000, $$gen_random_uuid()$$);
-- 0 years 0 mons 0 days 0 hours 0 mins 0.438084 secs