Как узнать, как далеко находится мой запрос к PostgreSQL?

35

У меня есть довольно приличное представление о том, сколько строк фактически обработает мой запрос SELECT ... INTO (например, я знаю, сколько из них материализуется).

Я понимаю, что Postgres не скажет мне процентную полноту, есть ли способ (скрытый глубоко в журналах, системных таблицах или иным образом), чтобы я мог узнать, сколько строк было добавлено в таблицу назначения или было прочитано запросом SELECT ?

Марк Эллиот
источник

Ответы:

33

Как отметил Даниэль Верите, похоже, нет общего решения. При загрузке данных в таблицу из файла можно использовать следующую технику для получения прогресса загрузки.

Индикатор выполнения консоли управления COPY

Создайте пустую таблицу.

CREATE TABLE mytest (n int);

Создайте файл данных с 10 миллионами строк для загрузки в таблицу.

$ seq 10000000 > /tmp/data.txt

Загрузите данные из файла в таблицу и отобразите индикатор выполнения.

$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"

демонстрация

введите описание изображения здесь

Как это работает

Используя опцию STDIN команд копирования, мы можем вводить данные для операции копирования из другого процесса. Команда pv выведет файл и отследит его прогресс, отобразив индикатор выполнения, ETA, общее время и скорость передачи данных.

Команда COPY графический индикатор выполнения

Используя ту же общую технику, мы могли бы отображать индикатор выполнения в графическом приложении или веб-приложении. Например, используя python, модуль psycopg2 позволяет вам вызывать команду копирования с выбранным вами файловым объектом. Затем вы можете отслеживать, сколько файлового объекта было прочитано, и отображать индикатор выполнения.

Марван Алсаббах
источник
2
Я не встречал эту pvкоманду раньше, и она не была установлена ​​на моем сервере Debian по умолчанию, но она находится в репозитории. В описании говорится, что «pv (Pipe Viewer) может быть вставлен в любой нормальный конвейер между двумя процессами, чтобы наглядно показать, как быстро проходят данные». Очень полезная команда!
Ричард Тернер
27

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

Последовательности

Если запрос SELECT или UPDATE включает в себя любой из них nextval(sequence_name), или INSERT имеет целевой столбец со значением nextvalпо умолчанию, текущее значение последовательности может быть повторно запрошено в другом сеансе SELECT sequence_name.last_value. Это работает, потому что последовательности не ограничены транзакциями. Когда план выполнения таков, что последовательность увеличивается линейно во время запроса, он может использоваться как индикатор прогресса.

pgstattuple

Pgstattuple модуль вно обеспечивает функции , которые могут PEEK непосредственно на страницах данных. Похоже, что когда кортежи вставляются в пустую таблицу и еще не зафиксированы, они учитываются в dead_tuple_countполе из pgstattupleфункции.

Демо с 9.1: создать пустую таблицу

CREATE TABLE tt AS (n numeric);

Давайте вставим 10M строк в него:

INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);

В другом сеансе проверяйте pgstattuple каждую секунду во время вставки:

$ while true;
   do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
   sleep 1;
  done

Полученные результаты:

0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0

Когда вставка завершена, она возвращается к 0 (все кортежи становятся видимыми и активными).

Этот прием также может быть использован, когда таблица не была заново создана, но инициал dead_tuple_count, вероятно, будет иметь ненулевое значение, и он также может измениться одновременно, если происходит другая операция записи, такая как autovacuum (предположительно? Не уверен, какой уровень параллелизма ожидать с автовакуумом).

Однако его нельзя использовать, если таблица создается самим оператором ( CREATE TABLE ... AS SELECTили SELECT * INTO newtable), поскольку создание выполняется. Обходной путь должен был бы создать таблицу без строк (добавить LIMIT 0) и заполнить ее в следующей транзакции.

Обратите внимание, что pgstattupleэто не бесплатно: он сканирует всю таблицу при каждом вызове. Также это ограничено суперпользователями.

Пользовательский счетчик

В блоге Павла Стегуле он предоставляет функцию счетчика, реализованную в C, которая вызывает NOTICEs при указанном количестве выполнений. Вы должны как-то объединить функцию с запросом, чтобы исполнитель вызвал ее. Уведомления отправляются во время запроса, и им не нужен отдельный сеанс, только клиент SQL, который их отображает ( psqlчто является очевидным кандидатом).

Пример INSERT INTO переработан для получения уведомлений:

/* transformation */
INSERT INTO destination_table
   SELECT (r).*
  FROM (SELECT counter(to_destination_table(_source), 1000, true) r
           FROM source _source) x

Связанный вопрос по stackoverflow, для функций:
Как сообщить о прогрессе от продолжительной функции PostgreSQL клиенту

Будущие варианты?

По состоянию на май 2017 года сообщество разработчиков представило многообещающий патч: [PATCH v2] Команда Progress для отслеживания хода выполнения длительных SQL-запросов.

который может закончиться как общее решение в PostgreSQL 11 или более поздней версии. Пользователи, которые хотят участвовать в незавершенных функциях, могут применить последнюю версию исправления и попробовать предложенную PROGRESSкоманду.

Даниэль Верите
источник
3

Пока функциональность отчета о проделанной работе не будет расширена, как @AmirAliAkbari упомянул в своем ответе, вот обходной путь на уровне ОС.

Это работает только в Linux, но, вероятно, существуют легко подобранные решения для любых операционных систем.

Самое большое преимущество , а также недостаток PostgreSQL, что все его движков простые однопоточных процессы, используя lseek(), read()и write()манипулировать их табличные файлы, в то время как они взаимодействуют на общих ают и замки.

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

Во-первых, вы можете увидеть PID бэкэнда из SELECT * FROM pg_stat_activity;:

29805270 | dbname  | 20019 |    16384 | username  |                  |             |                 |          -1 | 2018-09-19 21:31:57.68234+02  | 2018-09-19 21:31:59.435376+02 | 2018-09-\
20 00:34:30.892382+02 | 2018-09-20 00:34:30.892386+02 | Client          | ClientRead | active              |       92778 |        92778 |  INSERT INTO ...something...

Третий столбец - это пид. В PostgreSQL это то же самое, что и pid процесса Linux бэкэнда.

Затем вы можете связать его, например, с помощью strace -p 20019 -s 8192: ( -s 8192полезно, потому что postgresql работает с блоками длиной 8192 байта).

sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
recvfrom(10, "Q\0\0\1\267 INSERT <removed by @peterh>", 8192, 0, NULL, NULL) = 440
sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
lseek(298, 343634345)...
read(298, "<block data which was read in>"....
write(298, "<block data which was written out>"...

Значения:

  • sendtoпроисходит, если бэкэнд что-то отвечает клиенту. В этом примере он отвечает на результат INSERTзапроса.
  • recvfromпроисходит, если сервер получает что-то от клиента. Обычно это новый запрос, в примере еще один INSERT.
  • lseek происходит, если бэкэнд меняет положение в табличном файле.
  • read происходит, если бэкэнд читает блок из файла таблицы.
  • write происходит, если бэкэнд записывает блок в файл таблицы.

В случае readи write, вы также можете увидеть содержимое этого блока в таблице. Это может помочь понять, что он делает и где он.

В случае recvfrom, вы можете увидеть фактический запрос, что получил бэкэнд.

Петер говорит восстановить Монику
источник
2

Как сказано в других ответах, в настоящее время нет прямого пути для отчетности о прогрессе в целом.

PostgreSQL имеет возможность сообщать о ходе выполнения определенных команд во время их выполнения. В настоящее время единственной командой, которая поддерживает отчеты о ходе выполнения, является VACUUM. Это может быть расширено в будущем.

Однако, начиная с 9.6, всякий раз, когда VACUUM выполняется, pg_stat_progress_vacuumпредставление будет содержать по одной строке для каждого бэкэнда (включая рабочие процессы автоочистки), который в данный момент вакуумируется. Более подробную информацию pg_stat_progress_vacuumможно найти в документации: 27.4 Отчет о ходе работ .

Амир Али Акбари
источник