Як дізнатися, наскільки далеко знаходиться мій запит 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 забезпечує функції, які можуть зазирати безпосередньо на сторінки даних. Виявляється, що кортежі вставлені в порожню таблицю і ще не здійснені, вони рахуються в dead_tuple_countполі від pgstattupleфункції.

Демо з 9.1: створити порожню таблицю

CREATE TABLE tt AS (n numeric);

Вставимо в нього 10М рядків:

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, швидше за все, початкова матиме ненульове значення, а також може одночасно змінюватися, якщо відбувається інша активність запису, наприклад, автовакуум (мабуть? Не впевнений, на якому рівні одночасність очікувати з аутовакумом).

Однак його не можна використовувати, якщо таблиця створена самим оператором ( 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 згадував у своїй відповіді, ось вирішення рівня ОС.

Це працює лише на Linuxes, але, ймовірно, є легко схожі рішення для googlable для будь-яких операційних систем.

Найбільша перевага , а також недолік 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 Звіт про хід виконання .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.