4

我一直在分析我的应用程序的某些部分,我发现 PgAdmin3 在执行完全相同的脚本时比 psql 快得多。我正在使用 unix 套接字、Ubuntu 12.04 和 Postgresql 9.1 和 pgadmin3 v1.14。我有一个简单的脚本,如下所示:

BEGIN
INSERT INTO key_value(section,key,value) VALUES('section','key1','value');
....
INSERT INTO key_value(section,key,value) VALUES('section','key10000','value');
COMMIT;

这是表格:

CREATE TABLE key_value
(
  key text NOT NULL,
  value text,
  CONSTRAINT key_value_pkey PRIMARY KEY (section , key )
)
WITH (
  OIDS=FALSE
);

此脚本中有 10000 个插入。在 pgadmin3 中执行它大约需要 0.5 秒,在 psql 中执行它需要 2.5~3.5 秒。两者都包含在事务中,因此应该没有区别。在重新创建表、执行完全真空等操作后,结果是一致的。在 Postgresql 服务器中记录显示 postgres 在 psql 中执行时为每个插入语句记录日志,但从 pgadmin3 执行时只有一个日志。

psql 执行通过以下方式完成:

psql  -n -t -f p.sql -o/dev/null

并且还测试了

psql  -n -t -1 -f p.sql -o/dev/null

我的问题是为什么 psql 这么慢,为什么我们 postgresql 记录一个客户端中的每条语句,但只记录另一个客户端中的整个事务,以及是否有一个简单的 psql 修复。

编辑只是为了澄清,我正在记录持续时间而不是声明:

在服务器中,使用 psql 执行时我得到以下信息

2012-10-02 12:20:32 CEST LOG:  duration: 0.283 ms
....
2012-10-02 12:20:35 CEST LOG:  duration: 0.285 ms
2012-10-02 12:20:35 CEST LOG:  duration: 0.291 ms
2012-10-02 12:20:35 CEST LOG:  duration: 0.279 ms
2012-10-02 12:20:35 CEST LOG:  duration: 0.284 ms
2012-10-02 12:20:35 CEST LOG:  duration: 0.279 ms
2012-10-02 12:20:35 CEST LOG:  duration: 0.299 ms
....
2012-10-02 12:20:36 CEST LOG:  duration: 5.779 ms

使用 pgadmin3 执行时:

2012-10-02 12:23:21 CEST LOG:  duration: 532.695 ms

psql和pgadmin3中的用户和数据库相同

4

2 回答 2

3

我的提示:pgAdmin 将脚本作为一个多语句执行 - 因此网络(协议)开销更少。

于 2012-10-02T11:29:08.730 回答
1

psql具有将分号识别为语句分隔符的集成解析器。与 pgadmin 不同,它使用它将 SQL 脚本分解为多个语句,如Pavel 的回答中所述。

没有选项可以关闭此行为。但是,使用 DO 匿名代码块应该会获得类似的结果,只需很少的更改。如果你这样写脚本:

DO $$
BEGIN
INSERT INTO key_value(section,key,value) VALUES('section','key1','value');
....
INSERT INTO key_value(section,key,value) VALUES('section','key10000','value');
END $$;

这将与 pgadmin 一样一次性发送到服务器(尽管它在技术上完全不同),并且可能在相当的时间内执行。

编辑:根据@vseguip 评论,这不是有效的,因为 plpgsql 解释器在那些 10k 语句上花费了时间。

替代想法:将脚本更改为只有一个多行的 INSERT,而不是多个 INSERT,没有 DO 块。

BEGIN;
INSERT INTO key_value(section,key,value) VALUES('section','key1','value'),
      ('section','key2','value'),
      ('section','key3','value'),
      ....
      ('section','key10000','value');
END;
于 2012-10-02T14:45:42.813 回答