Здається, не існує загального, що підтримується методу, але є деякі хитрощі, які можуть бути використані в обмежених контекстах для оцінки ходу окремого запиту. Ось деякі з них.
Послідовності
Коли запит 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
команду.
pv
командою, і вона не була встановлена на моєму сервері Debian за замовчуванням, але це в репо. В описі йдеться про те, що "pv (Pipe Viewer) можна вставити в будь-який звичайний трубопровід між двома процесами, щоб візуально вказати на швидкість проходження даних". Дуже корисна команда!