Очень медленное ОБНОВЛЕНИЕ Postgres на большом столе - PullRequest
0 голосов
/ 11 марта 2012

У меня есть таблица Postgres 9.1.3 с 2,06 миллионами строк после WHERE Y = 1 , как показано ниже (всего в ней всего несколько десятков тысяч строк без WHERE ),Я пытаюсь добавить данные в пустое поле с помощью запроса, подобного следующему:

WITH B AS (
    SELECT Z,
           rank() OVER (ORDER BY L, N, M, P) AS X
    FROM   A
    WHERE  Y=1
)

UPDATE A
SET A.X = B.X
FROM B
WHERE A.Y=1
  AND B.Z = A.Z;

Этот запрос выполняется в течение нескольких часов и, по-видимому, выполняется очень медленно.Фактически, во второй раз, когда я попробовал это, у меня было отключение питания после того, как запрос выполнялся в течение ~ 3 часов.После восстановления питания я проанализировал таблицу и получил следующее:

INFO:  analyzing "consistent.master"
INFO:  "master": scanned 30000 of 69354 pages, containing 903542 live rows and 153552 dead rows; 30000 rows in sample, 2294502 estimated total rows
Total query runtime: 60089 ms.

Правильно ли интерпретировать, что запрос в те часы едва прогрессировал?

Я выполнил VACUUMFULL и ANALYZE перед выполнением длинного запроса.

Запрос в WITH занимает всего 40 секунд.

Все поля, указанные вышекроме AX и расширением BX индексируются: L, M, N, P, Y, Z.

Это выполняется на ноутбуке с 8 ГБ ОЗУ, четырехъядерным процессором Core i7 Q720 1,6 ГГц.и Windows 7 x64.Я использую Postgres 32 bit для совместимости с PostGIS 1.5.3.64-разрядная версия PostGIS для Windows еще не доступна.(32-битный Postgres означает, что он не может использовать более 2 ГБ ОЗУ в Windows, но я сомневаюсь, что здесь есть проблема.)

Вот результат EXPLAIN:

Update on A  (cost=727684.76..945437.01 rows=2032987 width=330)
  CTE B
    ->  WindowAgg  (cost=491007.50..542482.47 rows=2058999 width=43)
          ->  Sort  (cost=491007.50..496155.00 rows=2058999 width=43)
                Sort Key: A.L, A.N, A.M, A.P
                ->  Seq Scan on A  (cost=0.00..85066.80 rows=2058999 width=43)
                      Filter: (Y = 1)
  ->  Hash Join  (cost=185202.29..402954.54 rows=2032987 width=330)
        Hash Cond: ((B.Z)::text = (A.Z)::text)
        ->  CTE Scan on B  (cost=0.00..41179.98 rows=2058999 width=88)
        ->  Hash  (cost=85066.80..85066.80 rows=2058999 width=266)
              ->  Seq Scan on A  (cost=0.00..85066.80 rows=2058999 width=266)
                    Filter: (Y = 1)

Ответы [ 2 ]

4 голосов
/ 11 марта 2012

Может быть несколько решений.

  • Обновление может быть заблокировано при блокировке. Обратитесь к представлению pg_locks.
  • Может быть, на А есть триггеры? Они могут быть причиной замедления.
  • Попробуйте "объяснить обновление ..." - план значительно отличается от плана простого выбора? Возможно, вы могли бы сделать это в 2 этапа - экспортировать «B» в таблицу и обновить ее из этой таблицы.
  • Попробуйте сбросить индексы перед обновлением.
  • Создайте новую таблицу, удалите старую, переименуйте новую таблицу в имя старой таблицы.
0 голосов
/ 24 декабря 2014

Попробуйте переписать запрос так:

UPDATE A
SET A.X = B.X
FROM B
WHERE A.Y=1
      AND B.Z = A.Z
      AND A.X IS DISTINCT FROM B.X;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...