web-dev-qa-db-ja.com

準備済みステートメントのオーバーヘッド

Libpqxxを使用してPostgreSQL 9.3サーバーと通信しています。

複数のテーブル挿入の場合、それらが個別の準備済みステートメントに分割されると、それぞれ約2ミリ秒かかります。それらがすべて単一のCTEにまとめられる場合、準備されたステートメント全体のコストは約2msです。

実際、ほとんどすべての準備済みステートメントのコストは約2ミリ秒、ログに記録されていないテーブルの場合は1ミリ秒です。

これを正確に説明するものは何ですか?

編集する

最初に、最も高価な14個の準備済みステートメントのセットを2つのCTEに分割して、 単一行の書き込みルール を回避しました。

これにより、平均消費時間が40ミリ秒未満から約10ミリ秒に短縮されました。

単一行書き込みルールを回避するために、入力パラメーターを使用して関数を試しました。これはその便利さにもかかわらず災害であり、運転時間は約500msに費やされました。

単一のCTEを完了したばかりで、2つのCTEを半分で使用する場合と単一で使用する場合の違いはわかりませんが、いくつかの注意点があると思います。

2つのCTEをマージするには、テーブル間でデータを移動し、あるテーブルから別のテーブルにコピーし、そのソースデータを削除して再構築するため、 このソリューション のバリアントを使用する必要がありました。

新しいデータに存在しないキーは削除され、新しいデータがある場合は共存するキーが更新され、古いデータに存在しないキーが挿入され、削除+挿入が削除+更新+挿入に変換されます。

この準備されたCTEは、元の14クエリに対して、現在25クエリ近くあります。ただし、移動される行はごくわずかです。将来的には、さらに多くの行を移動する必要があります。

すべてのクエリが多かれ少なかれ同時に実行され、変更される行が少ないため、1つのCTEが2つのCTEと同じくらいの時間を消費するのは奇妙に思われます。私の推測では、このCTEははるかに大きいため、サーバーが最適なクエリプランを作成するには、より多くの試行が必要になります。

単一のCTEは、平均で5ミリ秒しか消費しません

クエリをさらに実行すると、平均が低下し始めました。現在は平均5ミリ秒に低下しています。 これはi7ラップトップ上にあります。まだクエリを何度も実行していないため、さらに改善の余地があるかもしれません。

私はPostgreSQLのソースコードについて知識がなく、同じボックス上にあるにもかかわらず、データベースとアプリケーション間のラウンドトリップによるパフォーマンスの程度を判断できないため、パフォーマンスの向上のほとんどすべてが原因であると私は推測しています。サブステートメントとメインクエリのデフォルトの同時実行を考慮したPostgreSQL CTEの効率。

うまくいけば、専門家が完全な説明を提供できると思いますが、私とパフォーマンスについては、すべてのプロセスを単一のCTEに詰め込もうとします。

3
Jim Bob

最後から2番目の主要な手順は、MySQLユーザーにとって残念なことに 結合が遅いMySQLのみ であることを確認することだったため、これらの書き込み集中型テーブルにはすべて、結合する一意の整数識別子が与えられました。これにより、残りの平均時間の消費量の1/3が削減されました。

最後のステップは CTE最適化フェンシング を考慮に入れることで、最後の2/3の削減を行いました。

上記のクエリセットの場合、付属のハードドライブを使用していても、SSD用に調整されたi7ラップトップで消費される平均時間は1〜2ミリ秒です。 SSDが1つのサーバーでは、消費される時間の平均は1ミリ秒未満です。

最後のパフォーマンスの向上を得るために、ほとんどすべてのクエリが圧縮されているため、たとえば、テーブルを更新する必要がある場合、どれほど奇妙に見えても、パフォーマンスが低下していても、1つのクエリで実行するのが最善です。

関連する主キー値を組み立てるための読み取りには、より多くのテストが必要でした。 RETURNINGの組み合わせの場合は、別のサブステートメントに依存して計算を行うのではなく、各サブステートメントが再計算できるようにするのが最善でした。読み取りが小さい場合でも、ディスクに書き込む必要がある場合は、一度実行して、複数の書き込みクエリで参照することをお勧めします。

コピーは別の灰色の領域でした。テーブルが別のテーブルのデータに基づいて挿入、更新、および削除を必要とする場合、データを事前に選択するのに時間がかかりました。主キーデータを単に参照する方が高速でした。

一般に、参照する主キー値をアセンブルするためにディスクに送信する読み取りを除いて、チェーンをできるだけ短く、狭く保つのは奇妙に見えるかもしれませんが、CTEをできるだけ圧縮することが最善です。

以前に私のアプリケーションで数十ミリ秒を消費した複数の準備されたステートメントトランザクションは、最大5ミリ秒を消費します。

このアプローチは、おそらく少量の冗長データに限定する必要があります。

2
Jim Bob