クエリを直接実行するのではなく、クエリを「準備」するときに、PostgreSQL(または他のデータベース)は内部で正確に何をしますか?
ループ内でINSERTが繰り返されることが非常に多い場合、ループの前に最初に「スケルトンの準備クエリ」を作成する傾向があります。ループでは、この準備されたクエリを「実行」してすべての値を送信します。私はずっと前に聞いたことがあり、抽象的な意味で、これは通常のパラメーター化されたクエリを含むループを持つよりも最適化されていることを理解できます。
しかし、PGが何をしているのか正確にはわかりません。それがとても速いなら。私は率直に言って、2つの異なる方法を比較するための実際のベンチマークを行ったことがありません。
また、クエリを非常に短い連続で数回(多くは言うまでもなく)繰り返した後、PGをクエリに「ウォームアップ」するべきではありません。おそらく、手動で行うのと同じことを行いますが、内部的には、通常のクエリを使用するだけです。パラメータ化されたクエリ?
私は、データベースが内部で何をしているのかを常に推測していることに気づきます。私はそれがどれほど「賢い」かを本当に理解していません。スマートコードによって内部的に処理されているため、意味のない多くのことをしているのではないかと心配しています。
たぶん、「準備」と「実行」は、最近では本当のメリットがない古風な慣習ですか?
PGは基本的に、今後の大量の同様のINSERTクエリの「準備」にリソースを割り当てているようですが、1つずつ実行する場合と比べて正確に何が異なるのかわかりません。また、INSERTで準備されていないクエリ/ステートメントのポイントが何であるかを理解していません。
PS:混乱を解消するために、パラメータ化されていないクエリは、準備されているかどうかに関係なく使用しません。多くの人が「パラメータ化されたクエリ」と「プリペアドステートメント」を混同しています。この質問では、後者を「準備されたクエリ」と呼んでも...
回答
実際、PostgreSQLでは、パラメーター化されたステートメントとプリペアドステートメントの違いはそれほど大きくありません。前者は内部的に名前のないプリペアドステートメントであり、主な違いは、次の名前のないプリペアドステートメントが来ると自動的に割り当てが解除されることです。
ステートメントを準備すると、PostgreSQLは現在のセッションでそのステートメントを記憶します(セッション間で何も共有されません)。
最初の5回の実行で、PostgreSQLはパラメーター値を考慮したカスタムクエリプランを生成します。その後、PostgreSQLはクエリパラメータに依存しない汎用プランを生成し、その汎用プランが以前のカスタムプランよりも高価でないと推定される場合は、その時点から使用されます。
説明したような挿入ステートメントの場合、PostgreSQLは常に汎用プランに切り替わります。主な利点は、クエリを計画する必要がないことです。簡単なステートメントでは、計画時間が実行時間を超える可能性があるため、大幅な節約が可能です。
PostgreSQLは、プリペアドステートメントおよびPL / pgSQL関数のステートメントのクエリプランのみをキャッシュします。
プリペアド(またはパラメーター化)ステートメントの他の利点は、SQLインジェクションの危険性を回避できることです。
多数の行を挿入する必要がある場合は、使用COPY
がさらに高速になります。