回答:
ダニエルベリテが述べたように、一般的な解決策はないようです。ファイルからテーブルにデータをロードする場合、次の手法を使用してロードの進行状況を取得できます。
COPYコマンドコンソールの進行状況バー
空のテーブルを作成します。
CREATE TABLE mytest (n int);
テーブルに読み込むための1,000万行のデータファイルを作成します。
$ seq 10000000 > /tmp/data.txt
ファイルからテーブルにデータを読み込み、進行状況バーを表示します。
$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"
デモ
仕組み
コピーコマンドのSTDINオプションを使用すると、別のプロセスからコピー操作のデータを入力できます。pvコマンドはファイルを出力し、その進行状況を追跡して、進行状況バー、ETA、合計経過時間、データ転送速度を表示します。
COPYコマンドのグラフィカルな進行状況バー
同じ一般的な手法を使用して、グラフィカルアプリケーションまたはWebベースのアプリケーションでプログレスバーを表示できます。たとえばpythonを使用して、psycopg2モジュールでは、選択したファイルオブジェクトでcopyコマンドを呼び出すことができます。その後、ファイルオブジェクトの読み取り量を追跡し、進行状況バーを表示できます。
サポートされている一般的なメソッドはないようですが、個々のクエリの進行状況を評価するために、限られたコンテキストで使用できるいくつかのトリックがあります。ここにそれらのいくつかがあります。
SELECTまたはUPDATEクエリにanyが含まれる場合nextval(sequence_name)
、またはINSERTにnextval
デフォルトとしてが含まれる宛先列がある場合、現在のシーケンス値はを使用して別のセッションで繰り返しクエリできますSELECT sequence_name.last_value
。シーケンスがトランザクションによって制限されていないため機能します。実行プランが、クエリ中にシーケンスが線形に増加するようなものである場合、進行インジケータとして使用できます。
pgstattupleののcontribモジュールは、データページに直接覗き見できる機能を提供します。タプルが空のテーブルに挿入され、まだコミットされていない場合、それらは関数の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などの他の書き込みアクティビティが実行されている場合も同時に変更される可能性があります(おそらく? autovacuumで予想される並行性)。
ただし、テーブル自体がステートメント(CREATE TABLE ... AS SELECT
またはSELECT * INTO newtable
)によって作成されている場合は、作成がトランザクション化されるため、使用できません。回避策は、行のないテーブルを作成し(add LIMIT 0
)、次のトランザクションでデータを追加することです。
pgstattuple
無料ではないことに注意してください:呼び出しごとにテーブル全体をスキャンします。また、スーパーユーザーに制限されています。
Pavel Stehuleのブログでは、 指定された実行回数で通知を発生させるCで実装されたカウンター関数を提供しています。executorが関数を呼び出すには、何らかの方法で関数をクエリと組み合わせる必要があります。通知はクエリ中に送信され、別個のセッションを必要とせず、それらを表示する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年5月の時点で、開発者コミュニティに提出された有望なパッチがあります。 [PATCH v2]実行時間の長いSQLクエリの進行を監視するProgressコマンド
PostgreSQL 11以降では一般的なソリューションになる可能性があります。進行中の機能に参加したいと考えているユーザーは、最新バージョンのパッチを適用し、提案されたPROGRESS
コマンドを試してください。
@AmirAliAkbariが彼の答えで述べたように、進行状況レポート機能が拡張されなくなるまで、OSレベルの回避策があります。
これはLinuxでのみ機能しますが、おそらくすべてのオペレーティングシステムで簡単にグーグル化できる同様のソリューションがあります。
そのバックエンドのすべてを使用して、シンプルなシングルスレッドのプロセスであることを最大の利点ともPostgreSQLのの欠点、lseek()
、read()
とwrite()
彼らは共有MEMとロックに相互作用している間に、そのテーブルのファイルを操作します。
この結果、すべてのバックエンドプロセスは常に単一のクエリで動作し、簡単に見つけることができ、簡単にstrace
d。
まず、以下からバックエンド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...
3列目はpidです。PostgreSQLでは、バックエンドのLinuxプロセスpidと同じです。
次に、たとえば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
、バックエンドが取得した実際のクエリを確認できます。
他の回答で述べたように、現在、一般的に進捗状況を報告する直接的な方法はありません。
PostgreSQLには、コマンド実行中に特定のコマンドの進行状況を報告する機能があります。現在、進捗レポートをサポートする唯一のコマンドはVACUUMです。これは将来拡張される可能性があります。
ただし、9.6以降、VACUUM
実行中の場合は常に、pg_stat_progress_vacuum
ビューには、現在バキューム処理している各バックエンド(自動バキュームワーカープロセスを含む)ごとに1つの行が含まれます。詳細についてpg_stat_progress_vacuum
は、ドキュメント:27.4 Progress Reportingをご覧ください。
pv
以前にこのコマンドに出くわすことはなかったし、デフォルトではDebianサーバーにインストールされていませんでしたが、リポジトリにあります。説明には、「pv(Pipe Viewer)を2つのプロセス間の通常のパイプラインに挿入して、データの通過速度を視覚的に示すことができる」とあります。非常に便利なコマンド!