1

我正在使用 Postgresql。我想测试一个函数执行需要多少时间。由于该函数只需要几毫秒,我想在循环中调用它 1000 次以获得准确的数字。

MySQL 有一个 BENCHMARK() 函数来执行此操作。是否有等价物或者我必须编写一个带有循环的程序才能做到这一点?

4

3 回答 3

3

在 PostgreSQL 中,您通常使用以下方法执行此操作generate_series

SELECT my_function()
FROM generate_series(1,5000);

或者

SELECT (SELECT my_query ....)
FROM generate_series(1,5000);

在后一种情况下,您可以添加OFFSET 0到子查询或将其包装在STRICTSQL 函数中,以防止查询计划器提取常见条件和子条款,否则会变得聪明。

可以使用 psql 的\timing命令 withSET log_duration = on或 with来获得EXPLAIN (ANALYZE, BUFFERS)时间,所有这些时间都略有不同 - 请参阅文档。简而言之,\timing衡量时间,包括往返和向客户的价值转移。log_duration测量服务器端执行时间。EXPLAIN (ANALYZE, BUFFERS)测量语句执行的细节,但增加了可能会减慢它的时间开销。

于 2012-10-20T16:24:06.133 回答
2

编写一个带循环的程序 - 不应超过 5 分钟。

于 2012-10-20T09:15:27.147 回答
-1
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
于 2021-04-04T14:12:12.633 回答