在简单查询上加入连接的异常缓慢的嵌套循环

时间:2020-05-03 19:17:10

标签: postgresql

我正在下面针对主键lt_id(pkey btree没有其他索引栏)运行查询,并针对1000个id进行连接。 可能只是我缺乏对Postgres的经验,但似乎速度慢了一个数量级。表中总共有80万行。

这是一台规格较低的机器(4G mem),但仍然认为它应该更快。 CPU处于空闲状态。

EXPLAIN (ANALYZE,BUFFERS) SELECT lt_id FROM "mytable" d INNER JOIN ( VALUES (1839147),(...998 more rows here...),(1756908)) v(id) ON (d.lt_id = v.id);

                                                              QUERY PLAN                                                               
---------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.42..7743.00 rows=1000 width=4) (actual time=69.852..20743.393 rows=1000 loops=1)
   Buffers: shared hit=2395 read=1607
   ->  Values Scan on "*VALUES*"  (cost=0.00..12.50 rows=1000 width=4) (actual time=0.004..4.770 rows=1000 loops=1)
   ->  Index Only Scan using lt_id_idx on mytable d  (cost=0.42..7.73 rows=1 width=4) (actual time=20.732..20.732 rows=1 loops=1000)
         Index Cond: (lt_id = "*VALUES*".column1)
         Heap Fetches: 1000
         Buffers: shared hit=2395 read=1607
 Planning Time: 86.284 ms
 Execution Time: 20744.223 ms
(9 rows)

psql 11.7,我使用的是9,但升级到11.7,没有观察到速度上的实际差异。

free
              total        used        free      shared  buff/cache   available
Mem:        3783732      158076     3400932       55420      224724     3366832
Swap:             0           0           0

即使规格不高,它真的应该花费20秒吗?实际上,许多其他查询花费的时间是原来的两倍或更多。 20秒似乎是最好的情况。表格中还有其他几个文本列,其中包含一些小文本文章,我怀疑这是问题所在。

我以前使用IN运算符,但观察到相似或较差的速度。 我还对默认配置进行了一些小的更改,但似乎并没有太大的区别。 work_mem = 32MB shared_buffers = 512MB

您对这台机器的预期性能有何想法?还是我可以尝试其他方法?

edit:我想我对实际循环中的时间感到好奇 实际时间= 20.732..20.732行= 1循环= 1000

似乎每个循环的实际时间小于或等于1ms,在最坏的情况下,对于1000次迭代,该时间小于1秒,其他操作似乎也可以忽略不计。这是否意味着问题很简单?慢盘?这里的情况通常是什么。 我注意到,如果我在只有8G内存但使用SSD的桌面上运行查询,查询速度将大大提高。 当然可以使用SSD,但是我想知道配置或查询/设置中的内容是否不是最佳选择。

1 个答案:

答案 0 :(得分:0)

按照@pifor的建议,设置track_io_timing = on可以看到,这实际上几乎完全是IO缓慢。

 Nested Loop  (cost=0.42..7743.00 rows=1000 width=69) (actual time=0.026..14901.004 rows=1000 loops=1)
   Buffers: shared hit=2859 read=1145
   I/O Timings: read=14861.578
   ->  Values Scan on "*VALUES*"  (cost=0.00..12.50 rows=1000 width=4) (actual time=0.002..5.497 rows=1000 loops=1)
   ->  Index Scan using mytable_pkey on mytable d  (cost=0.42..7.73 rows=1 width=69) (actual time=14.888..14.888 rows=1 loops=1000)
         Index Cond: (lt_id = "*VALUES*".column1)
         Buffers: shared hit=2859 read=1145
         I/O Timings: read=14861.578
 Planning Time: 0.420 ms
 Execution Time: 14901.734 ms
(10 rows)