简体   繁体   English

获取 PostgreSQL 查询的执行时间

[英]Get execution time of PostgreSQL query

DECLARE @StartTime datetime,@EndTime datetime

SELECT @StartTime=GETDATE()

select distinct born_on.name
from   born_on,died_on
where (FLOOR(('2012-01-30'-born_on.DOB)/365.25) <= (
    select max(FLOOR((died_on.DOD - born_on.DOB)/365.25))
    from   died_on, born_on
    where (died_on.name=born_on.name))
    )
and   (born_on.name <> All(select name from died_on))

SELECT @EndTime=GETDATE()

SELECT DATEDIFF(ms,@StartTime,@EndTime) AS [Duration in millisecs]

I am unable to get the query time.我无法获得查询时间。 Instead I get the following error:相反,我收到以下错误:

sql:/home/an/Desktop/dbms/query.sql:9: ERROR:  syntax error at or near "@"
LINE 1: DECLARE @StartTime datetime,@EndTime datetime

If you mean in psql, rather than some program you are writing, use \\?如果您的意思是在 psql 中,而不是您正在编写的某个程序,请使用\\? for the help, and see:如需帮助,请参阅:

\timing [on|off]       toggle timing of commands (currently off)

And then you get output like:然后你会得到如下输出:

# \timing on
Timing is on.

# select 1234;        
 ?column? 
----------
     1234
(1 row)

Time: 0.203 ms

There are various ways to measure execution time, each has pros and cons.有多种方法可以衡量执行时间,每种方法都各有利弊。 But whatever you do, some degree of the observer effect applies.但无论你做什么,都会有一定程度的观察者效应 Ie, measuring itself may distort the result.即,测量本身可能会扭曲结果。

1. EXPLAIN ANALYZE 1.解释EXPLAIN ANALYZE

You can prepend EXPLAIN ANALYZE , which reports the whole query plan with estimated costs actually measured times.您可以添加EXPLAIN ANALYZE ,它会报告整个查询计划以及实际测量时间的估计成本。 The query is actually executed (with all side -effect, if any!).查询实际执行(带有所有副作用,如果有的话!)。 Works for SELECT , INSERT , UPDATE , DELETE .适用于SELECTINSERTUPDATEDELETE

Check whether my adapted version of your query is, in fact, faster:检查我修改后的查询版本是否实际上更快:

EXPLAIN ANALYZE
SELECT DISTINCT born_on.name
FROM   born_on b
WHERE  date '2012-01-30' - b.dob <= (
    SELECT max(d1.dod - b1.dob)
    FROM   born_on b1
    JOIN   died_on d1 USING (name)  -- name must be unique!
    )
AND NOT EXISTS (
    SELECT FROM died_on d2
    WHERE  d2.name = b.name
    );

Execute a couple of times to get more comparable times with warm cache.执行几次以获得更多的热缓存可比时间。 Several options are available to adjust the level of detail.有几个选项可用于调整细节级别。

While mainly interested in total execution time , make it:虽然主要对总执行时间感兴趣,但让它:

EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)

Mostly, TIMING matters - the manual:大多数情况下, TIMING重要 -手册:

TIMING

Include actual startup time and time spent in each node in the output.在输出中包括实际启动时间和在每个节点上花费的时间。 The overhead of repeatedly reading the system clock can slow down the query significantly on some systems, so it may be useful to set this parameter to FALSE when only actual row counts, and not exact times, are needed.在某些系统上,重复读取系统时钟的开销会显着降低查询速度,因此当只需要实际行计数而不是确切时间时,将此参数设置为FALSE可能很有用。 Run time of the entire statement is always measured, even when node-level timing is turned off with this option.始终测量整个语句的运行时间,即使使用此选项关闭节点级计时也是如此。 [...] [...]

EXPLAIN ANALYZE measures on the server , using server time from the server OS, excluding network latency . EXPLAIN ANALYZE在服务器上测量,使用来自服务器操作系统的服务器时间,不包括网络延迟 But EXPLAIN adds some overhead to also output the query plan.但是EXPLAIN增加了一些开销来输出查询计划。

2. psql with \\timing 2. 带\\timing psql

Or use \\timing in psql.或者在 psql 中使用\\timing Like Peter demonstrates.就像彼得展示的那样。

The manual:手册:

\\timing [ on | off ]

With a parameter, turns displaying of how long each SQL statement takes on or off.使用参数,打开或关闭显示每个 SQL 语句花费的时间。 Without a parameter, toggles the display between on and off.如果没有参数,则在打开和关闭之间切换显示。 The display is in milliseconds;显示单位为毫秒; intervals longer than 1 second are also shown in minutes:seconds format, with hours and days fields added if needed.超过 1 秒的间隔也以分钟:秒格式显示,如果需要,可以添加小时和天字段。

Important difference: psql measures on the client using local time from the local OS, so the time includes network latency .重要区别: psql 使用本地操作系统的本地时间在客户端上进行测量,因此时间包括网络延迟 This can be a negligible difference or huge depending on connection and volume of returned data.根据连接和返回数据的数量,这可能是微不足道的差异或巨大的差异。

3. Enable log_duration 3. 启用log_duration

This has probably the least overhead per measurement and produces the least distorted timings.这可能是每次测量的开销最少,并且产生的时序失真最少。 But it's a little heavy-handed as you have to be superuser, have to adjust the server configuration, cannot just target the execution of a single query, and you have to read the server logs (unless you redirect to stdout ).但这有点笨手笨脚,因为您必须是超级用户,必须调整服务器配置,不能只针对单个查询的执行,而且您必须读取服务器日志(除非您重定向到stdout )。

The manual: 手册:

log_duration ( boolean ) log_duration ( boolean )

Causes the duration of every completed statement to be logged.导致记录每个已完成语句的持续时间。 The default is off .默认为off Only superusers can change this setting.只有超级用户才能更改此设置。

For clients using extended query protocol, durations of the Parse, Bind, and Execute steps are logged independently.对于使用扩展查询协议的客户端,解析、绑定和执行步骤的持续时间是独立记录的。

There are related settings like log_min_duration_statement .有相关设置,如log_min_duration_statement

4. Precise manual measurement with clock_timestamp() 4. 使用clock_timestamp()精确的手动测量

The manual: 手册:

clock_timestamp() returns the actual current time, and therefore its value changes even within a single SQL command. clock_timestamp()返回实际的当前时间,因此即使在单个 SQL 命令中它的值也会发生变化。

To get execution times for ad-hoc queries as exact as possible, the best I can think of is based on what filiprem provided - which is fine as is.为了尽可能准确地获得临时查询的执行时间,我能想到的最好的方法是基于filiprem 提供的内容- 这很好。
I refined it some more to filter measuring overhead - which can matter for cheap queries (but typically not for expensive ones) - especially if the underlying OS makes timing calls expensive:我对其进行了更多改进以过滤测量开销 - 这对于廉价查询可能很重要(但通常不适用于昂贵的查询) - 特别是如果底层操作系统使定时调用变得昂贵:

DO
$do$
DECLARE
   _start_ts1 timestamptz;
   _start_ts2 timestamptz;
   _start_ts  timestamptz;
   _end_ts1   timestamptz;
   _end_ts2   timestamptz;
   _end_ts    timestamptz;
   _overhead  numeric;     -- in ms
   _timing    numeric;     -- in ms
BEGIN
   _start_ts1 := clock_timestamp();
   _end_ts1   := clock_timestamp();
   _start_ts2 := clock_timestamp();
   _end_ts2   := clock_timestamp();
   -- take the minimum as conservative estimate
   _overhead  := 1000 * extract(epoch FROM LEAST(_end_ts1 - _start_ts1
                                               , _end_ts2 - _start_ts2));                     
   _start_ts := clock_timestamp();
   PERFORM 1;  -- your query here, replacing the outer SELECT with PERFORM
   _end_ts   := clock_timestamp();
   
   _timing := 1000 * (extract(epoch FROM _end_ts - _start_ts));
-- RAISE NOTICE 'Timing in ms = %'         , _timing;  -- optional info
-- RAISE NOTICE 'Timing overhead in ms = %', _overhead;
   RAISE NOTICE 'Execution time in ms = %' , _timing - _overhead;
END
$do$

Cost of timing itself varies wildly, depending on the underlying OS.计时本身的成本变化很大,具体取决于底层操作系统。 To get a hold of this, take start and end time a couple of times and take the minimum interval as conservative estimate for timing overhead.要掌握这一点,请几次开始和结束时间,并将最小间隔作为计时开销的保守估计。 Also, executing the function a couple of times should warm it up (if needed).此外,执行该函数几次应该会预热(如果需要)。

After measuring the execution time of the payload query, subtract that estimated overhead to get as close to the actual time as possible.在测量负载查询的执行时间后,减去估计的开销以尽可能接近实际时间。

Of course, it's more meaningful for cheap queries to loop 100000 times or execute it on a table with 100000 rows if you can, to make distracting noise insignificant.当然,如果可以的话,廉价查询循环 100000 次或在具有 100000 行的表上执行它更有意义,以使分散注意力的噪音变得无关紧要。

PostgreSQL is not Transact-SQL. PostgreSQL 不是 Transact-SQL。 These are two slightly different things.这是两件略有不同的事情。

In PostgreSQL, this would be something along the lines of在 PostgreSQL 中,这将类似于

DO $proc$
DECLARE
  StartTime timestamptz;
  EndTime timestamptz;
  Delta double precision;
BEGIN
  StartTime := clock_timestamp();
  PERFORM foo FROM bar; /* Put your query here, replacing SELECT with PERFORM */
  EndTime := clock_timestamp();
  Delta := 1000 * ( extract(epoch from EndTime) - extract(epoch from StartTime) );
  RAISE NOTICE 'Duration in millisecs=%', Delta;
END;
$proc$;

On the other hand, measuring query time does not have to be this complicated.另一方面,测量查询时间不必如此复杂。 There are better ways:有更好的方法:

  1. In postgres command line client there is a \\timing feature which measures query time on client side (similar to duration in bottomright corner of SQL Server Management Studio).postgres 命令行客户端中,有一个\\timing功能可以测量客户端的查询时间(类似于 SQL Server Management Studio 右下角的持续时间)。

  2. It's possible to record query duration in server log (for every query, or only when it lasted longer than X milliseconds).可以在服务器日志中记录查询持续时间(对于每个查询,或者仅当它持续超过 X 毫秒时)。

  3. It's possible to collect server-side timing for any single statement using the EXPLAIN command:可以使用EXPLAIN命令为任何单个语句收集服务器端计时:

     EXPLAIN (ANALYZE, BUFFERS) YOUR QUERY HERE;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM