获取 PostgreSQL 查询的执行时间

问题描述 投票:0回答:3
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
sql postgresql performance timing
3个回答
211
投票

如果您指的是 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

172
投票

衡量执行时间的方法有很多种,每种方法都有优点和缺点。但无论你做什么,都会产生一定程度的“观察者效应”。即,测量本身可能会扭曲结果。 1.

EXPLAIN ANALYZE

您可以在前面添加 

EXPLAIN ANALYZE

,它会报告整个查询计划以及实际测量时间的估计成本。该查询是实际执行的(有所有副作用,如果有的话!)。适用于所有 DDL 命令和其他一些命令。参见:

    解释分析不能与 ALTER TABLE 一起使用
  • 检查我对您的查询的改编版本实际上是否更快:

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 也增加了一些开销来输出查询计划。
2. psql 与 

\timing

或者在psql中使用

\timing

就像彼得演示的那样。

说明书:

\timing [ on | off ]

带参数,轮流显示每条SQL语句的长度
开启或关闭。如果没有参数,则在打开之间切换显示
然后关闭。显示单位为毫秒;间隔大于 1
第二个也以分钟:秒的格式显示,带有小时和天
如果需要添加字段。

重要区别:

psql 使用本地操作系统的本地时间在客户端测量,因此时间包括网络延迟。根据连接和返回数据量,这可能是一个可以忽略不计的差异或“巨大”。 3.启用log_duration

这可能每次测量的开销最小,并且产生的时序失真最小。但这有点繁琐,因为你必须是超级用户,必须调整服务器配置,不能只针对单个查询的执行,并且你必须读取服务器日志(除非你重定向到
stdout
)。

说明书:

log_duration

boolean

导致记录每个已完成语句的持续时间。这
默认为 
off
。只有超级用户才能更改此设置。

对于使用扩展查询协议的客户端,解析的持续时间, 绑定和执行步骤独立记录。


还有

log_min_duration_statement

等相关设置。

4.使用 
clock_timestamp()

进行精确的手动测量

说明书:

clock_timestamp()

返回实际的当前时间,因此即使在单个 SQL 命令内,其值也会发生变化。

filiprem 提供了

一种尽可能准确地获取临时查询执行时间的好方法。在现代硬件上,定时开销
应该

可以忽略不计,但根据主机操作系统的不同,它可能会有很大差异。通过服务器应用程序找出答案 pg_test_timing 否则你可以像这样过滤开销:

DO
$do$
DECLARE
   _timing1  timestamptz;
   _start_ts timestamptz;
   _end_ts   timestamptz;
   _overhead numeric;     -- in ms
BEGIN
   _timing1  := clock_timestamp();
   _start_ts := clock_timestamp();
   _end_ts   := clock_timestamp();
   -- take minimum duration as conservative estimate
   _overhead := 1000 * extract(epoch FROM LEAST(_start_ts - _timing1
                                              , _end_ts   - _start_ts));

   _start_ts := clock_timestamp();
   PERFORM 1;  -- your query here, replacing the outer SELECT with PERFORM
   _end_ts   := clock_timestamp();
   
-- RAISE NOTICE 'Timing overhead in ms = %', _overhead;
   RAISE NOTICE 'Execution time in ms = %' , 1000 * (extract(epoch FROM _end_ts - _start_ts)) - _overhead;
END
$do$;


重复计算时间(此处使用 3 个时间戳进行最低限度的计算)并选择最小间隔作为计时开销的保守估计。另外,执行函数

clock_timestamp()
 几次应该可以预热它(如果这对您的操作系统很重要)。

测量有效负载查询的执行时间后,减去估计的开销以更接近实际时间。

当然,如果可以的话,对于廉价查询来说,循环 100000 次或在具有 100000 行的表上执行它更有意义,以使分散注意力的噪音变得微不足道。

PostgreSQL 不是 Transact-SQL。这是两个略有不同的事情。


54
投票

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命令行客户端
    中有一个
  1. \timing

    功能可以测量客户端的查询时间(类似于SQL Server Management Studio右下角的持续时间)。

    可以在服务器日志中

    记录查询持续时间
  2. (对于每个查询,或者仅当其持续时间超过X毫秒时)。
  3. 可以使用

  4. EXPLAIN
  5. 命令收集任何单个语句的服务器端计时:

    EXPLAIN (ANALYZE, BUFFERS) YOUR QUERY HERE;
    

    	
© www.soinside.com 2019 - 2024. All rights reserved.