首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调试由pgbench执行的查询

调试由pgbench执行的查询
EN

Stack Overflow用户
提问于 2020-10-29 13:39:47
回答 1查看 119关注 0票数 0

我看到了pgbench的一个奇怪的输出,我不知道还有什么其他工具可以尝试理解延迟过大的原因。

下面是针对填充的explain数据库运行的pgbench结果:

代码语言:javascript
复制
pgbench=# explain analyze UPDATE pgbench_tellers SET tbalance = tbalance + 12345 WHERE tid = 100;
                                                   QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
 Update on pgbench_tellers  (cost=0.00..2.25 rows=1 width=358) (actual time=0.077..0.077 rows=0 loops=1)
   ->  Seq Scan on pgbench_tellers  (cost=0.00..2.25 rows=1 width=358) (actual time=0.023..0.025 rows=1 loops=1)
         Filter: (tid = 100)
         Rows Removed by Filter: 99
 Total runtime: 0.092 ms
(5 rows)

pgbench=# explain analyze UPDATE pgbench_branches SET bbalance = bbalance + 12345 WHERE bid = 10;
                                                    QUERY PLAN
------------------------------------------------------------------------------------------------------------------
 Update on pgbench_branches  (cost=0.00..1.13 rows=1 width=370) (actual time=0.045..0.045 rows=0 loops=1)
   ->  Seq Scan on pgbench_branches  (cost=0.00..1.13 rows=1 width=370) (actual time=0.027..0.028 rows=1 loops=1)
         Filter: (bid = 10)
         Rows Removed by Filter: 9
 Total runtime: 0.060 ms
(5 rows)

因此,根据规划师的说法,这两个查询应该在一个大致相同的位置上,而第二个查询可能会稍微快一些,因为它需要扫描的行较少。

然而,现实情况是:

代码语言:javascript
复制
  tps = 695.349735 (including connections establishing)
  tps = 695.355481 (excluding connections establishing)
  statement latencies in milliseconds:
          0.002471        \set nbranches 1 * :scale
          0.000743        \set ntellers 10 * :scale
          0.000684        \set naccounts 100000 * :scale
          0.000786        \setrandom aid 1 :naccounts
          0.000585        \setrandom bid 1 :nbranches
          0.000609        \setrandom tid 1 :ntellers
          0.000583        \setrandom delta -5000 5000
          0.124286        BEGIN;
          0.225984        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
          0.167551        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
          0.570490        UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
          3.230071        UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
          0.134970        INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CU
  RRENT_TIMESTAMP);                                                                                                    
          7.037875        END;

换句话说,在现实中被认为比实际完成速度快30%的查询完成速度慢了5000%。

到目前为止,我的猜测是,PostgreSQL计划器具有适用于低延迟存储的缺省值,但是,这些测试是针对具有潜在更高延迟(但也高队列深度和高带宽)的iSCSI设备执行的。

因此,我想知道是否有一种方法可以更详细地报告PostgreSQL在测试期间执行的I/O操作(从它的角度来看,我可以看到iSCSI门户端)。并且,如果可能的话,一种配置规划者的方法来调整其对“典型云”情况的估计,在这种情况下,延迟是很高的,但是队列深度和带宽也是如此。

在启用auto_explain和很少其他日志配置更改之后,下面是相关的输出:

代码语言:javascript
复制
LOG:  duration: 2667.835 ms  plan:
        Query Text: UPDATE pgbench_branches SET bbalance = bbalance + 3781 WHERE bid = 9;
        Update on pgbench_branches  (cost=4.26..8.27 rows=1 width=370) (actual time=2667.834..2667.834 rows=0 loops=1)
          Buffers: shared hit=11
          ->  Bitmap Heap Scan on pgbench_branches  (cost=4.26..8.27 rows=1 width=370) (actual time=0.010..0.010 rows=1 loops=1)
                Recheck Cond: (bid = 9)
                Buffers: shared hit=3
                ->  Bitmap Index Scan on pgbench_branches_pkey  (cost=0.00..4.26 rows=1 width=0) (actual time=0.003..0.003 rows=1 loops=1)
                      Index Cond: (bid = 9)
                      Buffers: shared hit=2

LOG:  duration: 9.604 ms  plan:
        Query Text: UPDATE pgbench_tellers SET tbalance = tbalance + 3845 WHERE tid = 33;
        Update on pgbench_tellers  (cost=0.00..8.28 rows=1 width=358) (actual time=9.604..9.604 rows=0 loops=1)
          Buffers: shared hit=7
          ->  Index Scan using pgbench_tellers_pkey on pgbench_tellers  (cost=0.00..8.28 rows=1 width=358) (actual time=0.009..0.010 rows=1 loops=1)
                Index Cond: (tid = 33)
                Buffers: shared hit=3

因此,区别似乎是在Bitmap Heap Scan + Bitmap Index ScanIndex Scan之间。我仍然不知道为什么会有不同,它在I/O方面意味着什么。

更新2

从更多关于各种扫描以及使用这些扫描背后的理由的阅读来看,PostgreSQL似乎选择对更大的表使用Index Scan,因为它认为大多数结果与查询无关,而使用Bitmap Heap Scan是因为它认为结果集将足够小,从而更容易扫描“一切”,然后过滤掉不必要的结果(不会有太多结果)。然而,由于巨大的延迟影响,堆扫描最终被证明是错误的策略。

更新3

我以前的解释是错的。或者,至少不是完整的答案。添加I/O时间报告和锁时间报告后,PostgreSQL等待获取锁的时间似乎是延迟的原因。现在,更大的问题是,为什么更大的表上的争用要高得多,或者是否还有其他机制使这些锁非常慢(有时超过3秒)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-02 06:50:01

除非您在数据库上运行的是pgbench之外的其他东西,否则任何东西都不会锁定您2秒。

此外,位图堆扫描没有出错(速度很快),而是更新本身。

最可能的原因是I/O过载-检查CPU花费的I/O等待时间。

另一种(不太可能的)可能性,也许与前一种可能相结合,是一个很小的shared_buffers,因此后端找不到干净的缓冲区。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64592280

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档