Неоправданно медленная Nested L oop с объединением по простому запросу - PullRequest
1 голос
/ 03 мая 2020

Я выполняю приведенный ниже запрос к первичному ключу lt_id (без другого индексного бара, кроме pkey btree) и присоединяюсь к 1000 идентификаторам. Это может быть просто мой недостаток опыта с postgres, но, похоже, это может быть на порядок медленнее. Всего в таблице 800k строк.

Это машина с низкой скоростью c (4G mem) но все же думал, что это должно быть быстрее. Процессор простаивает.

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

Несмотря на низкую скорость c действительно ли это займет 20 секунд? На самом деле многие другие запросы занимают вдвое больше или больше. 20 секунд, кажется, лучший вариант развития событий. В таблице есть несколько других текстовых столбцов с небольшими текстовыми статьями, в которых я сомневаюсь, что проблема.

Ранее я использовал оператор IN, но наблюдал схожие или худшие скорости. Я также внес несколько небольших изменений в конфигурацию по умолчанию, но, похоже, это не имеет большого значения. work_mem = 32 МБ shared_buffers = 512 МБ

Есть идеи, если это ожидаемая производительность на данной машине? Или есть что-то еще, что я могу попробовать?

edit: Я думаю, что мне интересно, что время в реальном времени фактического цикла = 20.732..20.732 строк = 1 циклов = 1000

Кажется, что фактическое время меньше или равно 1 мс на л oop, что в худшем случае будет меньше 1 секунды на 1000 итераций, а другие операции также кажутся незначительными. Означает ли это, что проблема в простом IO? медленный диск? Какова обычно была бы ситуация здесь. Я замечаю, что если я запускаю запрос на своем рабочем столе, который имеет только 8 ГБ оперативной памяти, но использует SSD, запрос выполняется значительно быстрее. Конечно, использование SSD это хорошо, но я хотел бы знать, есть ли что-то в моей конфигурации или запросе / настройке не оптимально ..

1 Ответ

0 голосов
/ 04 мая 2020

Как и предположил @pifor, установите track_io_timing = on, и вы увидите, что это почти полностью медленная скорость ввода-вывода ..

 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...