Долгое ОБНОВЛЕНИЕ в postgresql - PullRequest
6 голосов
/ 07 января 2009

Я выполняю ОБНОВЛЕНИЕ для таблицы, содержащей 250 миллионов строк с 3 индексами '; это ОБНОВЛЕНИЕ использует другую таблицу, содержащую 30 миллионов строк. Он работает уже около 36 часов. Мне интересно, если это способ выяснить, насколько это близко к тому, что делается, если он планирует потратить миллион дней, чтобы сделать свое дело, я его убью; но если ему понадобится еще день или два, я позволю ему бежать. Вот команда-запрос:

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0
;

Объяснение здесь не является проблемой, и я только упомяну, что большая таблица имеет несколько индексов, чтобы несколько оправдать, сколько времени требуется, чтобы ОБНОВИТЬ ее. Но в любом случае вот ОБЪЯСНЕНИЕ:

Merge Join  (cost=127710692.21..135714045.43 rows=452882848 width=57)
  Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?"))
  ->  Sort  (cost=3193335.39..3219544.38 rows=10483593 width=41)
        Sort Key: page.page_namespace, (page.page_title)::text
        ->  Seq Scan on page  (cost=0.00..439678.01 rows=10483593 width=41)
              Filter: (page_is_redirect = 0::numeric)
  ->  Sort  (cost=124517356.82..125285665.74 rows=307323566 width=46)
        Sort Key: pagelinks.pl_namespace, (pagelinks.pl_title)::text"
        ->  Seq Scan on pagelinks  (cost=0.00..6169460.66 rows=307323566 width=46)

Теперь я также отправил параллельную команду запроса, чтобы УБРАТЬ один из pagelinks ' indexes; конечно, он ждет, пока ОБНОВЛЕНИЕ закончится (но я все равно хотел попробовать это!). Следовательно, я не могу ВЫБРАТЬ что-либо из pagelinks из-за боязни повредить данные (разве вы думаете, что было бы безопасно уничтожить процесс постмастера DROP INDEX?).

Так что мне интересно, будет ли это таблица, в которой будет отслеживаться количество мертвых кортежей или что-то в этом роде. Было бы неплохо узнать, насколько быстро или как далеко находится ОБНОВЛЕНИЕ в завершении своей задачи.

Thx (PostgreSQL не такой умный, как я думал; ему нужна эвристика)

Ответы [ 3 ]

4 голосов
/ 09 января 2009

Читали ли вы документацию PostgreSQL для " Использование EXPLAIN ", чтобы интерпретировать вывод, который вы показываете?

Я не обычный пользователь PostgreSQL, но я просто прочитал этот документ, а затем сравнил с выводом EXPLAIN, который вы показываете. Ваш запрос UPDATE, похоже, не использует индексы, и он вынужден выполнять сканирование таблиц для сортировки page и pagelinks. Сортировка, без сомнения, достаточно велика, чтобы требовать временные файлы на диске, которые, я думаю, создаются под вашим temp_tablespace.

Тогда я вижу приблизительные прочитанные страницы базы данных. Верхний уровень этого вывода EXPLAIN говорит (cost=127710692.21..135714045.43). Единицы здесь находятся в доступе дискового ввода-вывода. Таким образом, он получит доступ к диску более 135 миллионов раз, чтобы сделать это UPDATE.

Обратите внимание, что даже 10 000 об / мин дисков с временем поиска 5 мсек могут достичь в лучшем случае 200 операций ввода-вывода в секунду при оптимальных условиях. Это будет означать, что на UPDATE потребуется 188 часов (7,8 дня) дискового ввода-вывода, даже если вы могли бы поддерживать насыщенный дисковый ввод-вывод в течение этого периода (то есть непрерывного чтения / записи без перерывов). Это невозможно, и я ожидаю, что фактическая пропускная способность будет по крайней мере на порядок меньше, тем более что вы без сомнения использовали этот сервер для всех видов другой работы. Так что я думаю, что вы только часть пути через ваш UPDATE.

Если бы это был я, я бы убил этот запрос в первый день и нашел бы другой способ выполнения UPDATE, который бы лучше использовал индексы и не требовал сортировки на диске. Вы, вероятно, не можете сделать это в одном выражении SQL.

Что касается вашего DROP INDEX, я бы предположил, что это просто блокировка, ожидание монопольного доступа к таблице, и пока он находится в этом состоянии, я думаю, вы, вероятно, можете его убить.

1 голос
/ 20 сентября 2018

Это очень старая версия, но если вы хотите, чтобы у вас был способ отслеживать ваше обновление ... Помните, что на последовательности влияют глобально, так что вы можете просто создать такую, чтобы отслеживать это обновление в другой сессии, выполнив это:

create sequence yourprogress; 

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;

Затем в другом сеансе просто сделайте это (не беспокойтесь о транзакциях, поскольку последовательности затронуты глобально):

select last_value from yourprogress;

Это покажет, сколько линий затронуто, так что вы можете оценить, сколько времени вам потребуется.

В конце перезапустите последовательность, чтобы повторить попытку:

alter sequence yourprogress restart with 1;

Или просто бросьте:

drop sequence yourprogress;
0 голосов
/ 09 января 2009

Вам нужны индексы, или, как указал Билл, для всех таблиц потребуется последовательное сканирование.

CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...