[英]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]
我无法获得查询时间。 相反,我收到以下错误:
sql:/home/an/Desktop/dbms/query.sql:9: ERROR: syntax error at or near "@"
LINE 1: DECLARE @StartTime datetime,@EndTime datetime
如果您的意思是在 psql 中,而不是您正在编写的某个程序,请使用\\?
如需帮助,请参阅:
\timing [on|off] toggle timing of commands (currently off)
然后你会得到如下输出:
# \timing on
Timing is on.
# select 1234;
?column?
----------
1234
(1 row)
Time: 0.203 ms
有多种方法可以衡量执行时间,每种方法都各有利弊。 但无论你做什么,都会有一定程度的观察者效应。 即,测量本身可能会扭曲结果。
EXPLAIN ANALYZE
您可以添加EXPLAIN ANALYZE
,它会报告整个查询计划以及实际测量时间的估计成本。 查询实际执行(带有所有副作用,如果有的话!)。 适用于SELECT
、 INSERT
、 UPDATE
、 DELETE
。
检查我修改后的查询版本是否实际上更快:
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
);
执行几次以获得更多的热缓存可比时间。 有几个选项可用于调整细节级别。
虽然主要对总执行时间感兴趣,但让它:
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
大多数情况下, TIMING
重要 -手册:
TIMING
在输出中包括实际启动时间和在每个节点上花费的时间。 在某些系统上,重复读取系统时钟的开销会显着降低查询速度,因此当只需要实际行计数而不是确切时间时,将此参数设置为
FALSE
可能很有用。 始终测量整个语句的运行时间,即使使用此选项关闭节点级计时也是如此。 [...]
EXPLAIN ANALYZE
在服务器上测量,使用来自服务器操作系统的服务器时间,不包括网络延迟。 但是EXPLAIN
增加了一些开销来输出查询计划。
\\timing
psql 或者在 psql 中使用\\timing
。 就像彼得展示的那样。
\\timing [ on | off ]
使用参数,打开或关闭显示每个 SQL 语句花费的时间。 如果没有参数,则在打开和关闭之间切换显示。 显示单位为毫秒; 超过 1 秒的间隔也以分钟:秒格式显示,如果需要,可以添加小时和天字段。
重要区别: psql 使用本地操作系统的本地时间在客户端上进行测量,因此时间包括网络延迟。 根据连接和返回数据的数量,这可能是微不足道的差异或巨大的差异。
log_duration
这可能是每次测量的开销最少,并且产生的时序失真最少。 但这有点笨手笨脚,因为您必须是超级用户,必须调整服务器配置,不能只针对单个查询的执行,而且您必须读取服务器日志(除非您重定向到stdout
)。
log_duration
(boolean
)导致记录每个已完成语句的持续时间。 默认为
off
。 只有超级用户才能更改此设置。对于使用扩展查询协议的客户端,解析、绑定和执行步骤的持续时间是独立记录的。
有相关设置,如log_min_duration_statement
。
clock_timestamp()
精确的手动测量
clock_timestamp()
返回实际的当前时间,因此即使在单个 SQL 命令中它的值也会发生变化。
为了尽可能准确地获得临时查询的执行时间,我能想到的最好的方法是基于filiprem 提供的内容- 这很好。
我对其进行了更多改进以过滤测量开销 - 这对于廉价查询可能很重要(但通常不适用于昂贵的查询) - 特别是如果底层操作系统使定时调用变得昂贵:
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$
计时本身的成本变化很大,具体取决于底层操作系统。 要掌握这一点,请几次开始和结束时间,并将最小间隔作为计时开销的保守估计。 此外,执行该函数几次应该会预热(如果需要)。
在测量负载查询的执行时间后,减去估计的开销以尽可能接近实际时间。
当然,如果可以的话,廉价查询循环 100000 次或在具有 100000 行的表上执行它更有意义,以使分散注意力的噪音变得无关紧要。
PostgreSQL 不是 Transact-SQL。 这是两件略有不同的事情。
在 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$;
另一方面,测量查询时间不必如此复杂。 有更好的方法:
在postgres 命令行客户端中,有一个\\timing
功能可以测量客户端的查询时间(类似于 SQL Server Management Studio 右下角的持续时间)。
可以在服务器日志中记录查询持续时间(对于每个查询,或者仅当它持续超过 X 毫秒时)。
可以使用EXPLAIN
命令为任何单个语句收集服务器端计时:
EXPLAIN (ANALYZE, BUFFERS) YOUR QUERY HERE;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.