测量执行 PostgreSQL 查询所需的时间

发布于 2025-01-11 05:59:56 字数 888 浏览 0 评论 0原文

基于 测量执行 t- 所需的时间sql查询,如何在PostgreSQL中多次尝试一个查询?

总体轮廓是 -- 设置试验次数(比如 1000)

SELECT CURRENT_DATE ; -- save start time

BEGIN
  LOOP
    -- execute query to be tested
 END LOOP;
END;

SELECT CURRENT_DATE ; -- save end time
    

IE 我想要一个相当于以下 TSQL 代码的 PostgreSQL,该代码取自 HumbleWebDev 从链接的 TSQL 问题中得到的答案: 参见[代码参考] 声明@tTOTAL int = 0 声明@i整数= 0 声明 @itrs integer = 100

while @i < @itrs
begin
declare @t0 datetime = GETDATE()

--your query here

declare @t1 datetime = GETDATE()

set @tTotal = @tTotal + DATEDIFF(MICROSECOND,@t0,@t1)

set @i = @i + 1
end

select @tTotal/@itrs

-- 您的查询在这里:标准 SQL 查询,例如 Select * from table1 inside -- join table2,或执行存储过程等。

Based on Measure the time it takes to execute a t-sql query, how would one time several trials of a query in PostgreSQL?

A general outline would be
-- set up number of trials (say 1000)

SELECT CURRENT_DATE ; -- save start time

BEGIN
  LOOP
    -- execute query to be tested
 END LOOP;
END;

SELECT CURRENT_DATE ; -- save end time
    

I.E. I want a PostgreSQL equivalent of the following TSQL code, taken from an answer by HumbleWebDev from the linked TSQL question: see [reference for code]

declare @tTOTAL int = 0
declare @i integer = 0
declare @itrs integer = 100

while @i < @itrs
begin
declare @t0 datetime = GETDATE()

--your query here

declare @t1 datetime = GETDATE()

set @tTotal = @tTotal + DATEDIFF(MICROSECOND,@t0,@t1)

set @i = @i + 1
end

select @tTotal/@itrs

-- your query here: Standard SQL queries such as Select * from table1 inner -- join table2, or executing stored procedure, etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨与橙与城 2025-01-18 05:59:56

我自己有 MSSQL 背景,现在更多地在 Postgres 中工作,我能感受到你的痛苦 =)

Postgres 的“麻烦”是它只支持“基本”SQL 命令(SELECT、INSERT、UPDATE、CREATE、ALTER 等...... )但是当你想要添加逻辑(IF THEN、WHILE、变量等)时,你需要切换到 pl/pgsql,它只能在函数内部使用(AFAIK)。从 TSQL POV 来看,存在相当多的限制,事实上,有些事情突然不再起作用(或者需要以不同的方式完成......例如 SELECT * INTO TEMPORARY TABLE tempTable FROM someTable 将不起作用,但是CREATE TABLE tempTable AS SELECT * FROM someTable 会)

我也以惨痛的教训学到了 CURRENT_TIMESTAMP (或 Now())将在事务中返回相同的值。由于函数内的所有内容都在事务内运行,这意味着您必须使用 Clock_timstamp()

无论如何,要回答您的问题,我认为这应该可以帮助您:

CREATE OR REPLACE FUNCTION fn_test ( nbrOfIterations int)
RETURNS TABLE (iterations int, totalTime interval, secondsPerIteration int)
AS $
DECLARE 

    i         int;
    startTime TIMESTAMP;
    endTime   TIMESTAMP;
    dummy     text;

BEGIN

    i := 1;
    startTime := clock_timestamp();

    WHILE ( i <=  nbrOfIterations) LOOP
    
        -- your query here
        -- (note: make sure to not return anything or you'll get an error)

        -- example:
        SELECT pg_sleep INTO dummy FROM pg_sleep(1);

        i := i + 1;

    END LOOP;

    endTime := clock_timestamp();

    iterations := nbrOfIterations;
    totalTime := (endTime - startTime);
    secondsPerIteration := (EXTRACT(EPOCH FROM endTime) - EXTRACT(EPOCH FROM startTime)) / iterations;


    RETURN NEXT;

END;
$ language plpgsql;


SELECT * FROM fn_test(5);

Coming from an MSSQL background myself and now more often working in Postgres I feel your pain =)

The "trouble" with Postgres is that it supports only 'basic' SQL commands (SELECT, INSERT, UPDATE, CREATE, ALTER, etc...) but the moment you want to add logic (IF THEN, WHILE, variables, etc.) you need to switch to pl/pgsql which you can only use inside functions (AFAIK). From a TSQL POV there are quite some limitations and in fact, some things suddenly don't work anymore (or need to be done differently.. e.g. SELECT * INTO TEMPORARY TABLE tempTable FROM someTable will not work but CREATE TABLE tempTable AS SELECT * FROM someTable will)

Something I learned the hard way too is that CURRENT_TIMESTAMP (or Now()) will return the same value within a transaction. And since everything inside a function runs inside a transaction this means you have to use clock_timstamp()

Anyway, to answer your question, I think this should get you going:

CREATE OR REPLACE FUNCTION fn_test ( nbrOfIterations int)
RETURNS TABLE (iterations int, totalTime interval, secondsPerIteration int)
AS $
DECLARE 

    i         int;
    startTime TIMESTAMP;
    endTime   TIMESTAMP;
    dummy     text;

BEGIN

    i := 1;
    startTime := clock_timestamp();

    WHILE ( i <=  nbrOfIterations) LOOP
    
        -- your query here
        -- (note: make sure to not return anything or you'll get an error)

        -- example:
        SELECT pg_sleep INTO dummy FROM pg_sleep(1);

        i := i + 1;

    END LOOP;

    endTime := clock_timestamp();

    iterations := nbrOfIterations;
    totalTime := (endTime - startTime);
    secondsPerIteration := (EXTRACT(EPOCH FROM endTime) - EXTRACT(EPOCH FROM startTime)) / iterations;


    RETURN NEXT;

END;
$ language plpgsql;


SELECT * FROM fn_test(5);
画尸师 2025-01-18 05:59:56

虽然接受的答案是正确的,但这种调整对我来说效果更好。再次,我想强调下面这个额外的答案是基于上面的答案,没有它就不可能。在我自己的情况下使用我下面所做的调整效果更好。

下面的答案确实几乎完全基于已接受的答案。但是,我更改了返回的使用方式,并将秒更改为毫秒:

----------------------------------------------------------------------------------------------------
-- fn__myFunction_Q.sql
----------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------
-- DROP FUNCTION mySchema.fn__myFunction
--------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION mySchema.fn__myFunction ( nbrOfIterations int)
RETURNS TABLE (iterations int, totalTime interval, millisecondsPerIteration int) -- interval --  
AS $
declare

i         int;
startTime TIMESTAMP;
endTime   TIMESTAMP;
-- dummy     text;
iterations int;
millisecondsPerIteration int;
totalTime interval;

BEGIN

    i := 1;
    startTime := clock_timestamp();

    WHILE ( i <=  nbrOfIterations) LOOP
     PERFORM /* Put your query here, replacing SELECT with PERFORM */
--------------------------------------------------------------------------------------------
--SELECT 
    -- YOUR QUERY HERE 
    -- ...
--------------------------------------------------------------------------------------------
        i := i + 1; -- very important to increment loop counter, else one gets an infinite loop!!!

    END LOOP;

    endTime := clock_timestamp();

    iterations := nbrOfIterations;
    totalTime := (endTime - startTime);
    millisecondsPerIteration := 1000 * (EXTRACT(EPOCH FROM endTime) - EXTRACT(EPOCH FROM startTime)) / iterations;
    RETURN QUERY  select iterations, totalTime, millisecondsPerIteration; 
    -- RETURNS TABLE (iterations int, totalTime interval, secondsPerIteration int) -- interval --  

    -- RETURN NEXT;

END;
$ language plpgsql;

--------------------------------------------------------------------------------------------

要调用此函数,只需使用:

SELECT * from mySchema.fn__myFunction(1000) as ourTableResult;

While the accepted answer is correct, this tweaking of it worked better for me. Again, I want to emphasize this extra answer below is based on the above answer, and it would not be possible without it. It just works better in my own situation to use the tweak I made below.

The answer below is indeed almost entirely based on the accepted answer. However, I changed how the return is used and also seconds to milliseconds:

----------------------------------------------------------------------------------------------------
-- fn__myFunction_Q.sql
----------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------
-- DROP FUNCTION mySchema.fn__myFunction
--------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION mySchema.fn__myFunction ( nbrOfIterations int)
RETURNS TABLE (iterations int, totalTime interval, millisecondsPerIteration int) -- interval --  
AS $
declare

i         int;
startTime TIMESTAMP;
endTime   TIMESTAMP;
-- dummy     text;
iterations int;
millisecondsPerIteration int;
totalTime interval;

BEGIN

    i := 1;
    startTime := clock_timestamp();

    WHILE ( i <=  nbrOfIterations) LOOP
     PERFORM /* Put your query here, replacing SELECT with PERFORM */
--------------------------------------------------------------------------------------------
--SELECT 
    -- YOUR QUERY HERE 
    -- ...
--------------------------------------------------------------------------------------------
        i := i + 1; -- very important to increment loop counter, else one gets an infinite loop!!!

    END LOOP;

    endTime := clock_timestamp();

    iterations := nbrOfIterations;
    totalTime := (endTime - startTime);
    millisecondsPerIteration := 1000 * (EXTRACT(EPOCH FROM endTime) - EXTRACT(EPOCH FROM startTime)) / iterations;
    RETURN QUERY  select iterations, totalTime, millisecondsPerIteration; 
    -- RETURNS TABLE (iterations int, totalTime interval, secondsPerIteration int) -- interval --  

    -- RETURN NEXT;

END;
$ language plpgsql;

--------------------------------------------------------------------------------------------

To call this function, just use:

SELECT * from mySchema.fn__myFunction(1000) as ourTableResult;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文