2012-03-10 5 views
0

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

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. 

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

Я сделал VACUUM ПОЛНОГО и ANALYZE перед запуском длинного запроса.

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

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

Это выполняется на ноутбуке с 8 Гб оперативной памяти, а Core i7 Q720 с тактовой частотой 1,6 ГГц и Windows 7 x64. Я запускаю Postgres 32 бит для совместимости с 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) 
+0

Я не понимаю, цифры. Таблица содержит 2 миллиона строк. Сколько строк выполняет условие 'WHERE Y = 1'? –

+2

Опубликовать 'EXPLAIN' или (если он завершает) вывод' EXPLAIN ANALYZE', пожалуйста. –

+0

Если часть 'Y = 1' является очень избирательной (как в моих случайно сгенерированных данных), обновление выполняется в миллисекундах. Поэтому, пожалуйста, укажите пример данных [sscce.org] (http://sscce.org/). –

ответ

2

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

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

Моя ставка зависит от проблемы с блокировкой (b). Я пробовал обновление на моем довольно устаревшем рабочем столе и обновлял 2 миллиона строк, а исходное заявление заняло около 4 минут. –

+0

Я единственный пользователь этой БД. Разве это не исключало бы (б) блокировку? Нет триггеров. Результаты EXPLAIN находятся в моем отредактированном сообщении. Я думаю, что он разделяет UDPATE и SELECT? Хорошее представление о 2-й таблице; Я посмотрю, смогу ли я попробовать это позже сегодня. –

+0

Просто убедитесь, что вы написали «отбрасывание индексов перед обновлением». Разве это не ухудшит ситуацию? Обновленное поле (** A.X **) не индексируется, и у меня есть ** WHERE ** предложения, включающие ** A.Y ** и ** A.Z **. –

0

Попытка переписать запрос так:

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; 
Смежные вопросы