sql >> データベース >  >> RDS >> PostgreSQL

(SELECT)クエリはいつ計画されますか?

    クライアント側のPerlインターフェース自体について話すことはできませんが、PostgreSQLサーバー側に光を当てることはできます。

    PostgreSQLには、プリペアドステートメントとプリペアドステートメントがあります。準備されていないステートメントは、すぐに解析、計画、実行されます。また、しません パラメータ置換をサポートします。プレーンなpsql シェルでは、次のようにクエリプランを表示できます:

    tmpdb> explain select * from sometable where flag = true;
    

    一方、プリペアドステートメントがあります。これらは通常(以下の「例外」を参照)、1つのステップで解析および計画され、2番目のステップで実行されます。 実行するため、さまざまなパラメータを使用して複数回再実行できます。 パラメータ置換をサポートします。 psqlの同等物 これは:

    tmpdb> prepare foo as select * from sometable where flag = $1;
    tmpdb> explain execute foo(true);
    

    計画はprepareですでに行われているため、計画は準備されていないステートメントの計画とは異なることがわかります。 準備 のドキュメントに記載されているフェーズ :

    これは、計画がないことも意味します。 置換されたパラメータ用に最適化:最初の例では、flagのインデックスを使用する場合があります PostgreSQLは、100万エントリ以内で値がtrueであるのは10個だけであることを認識しているためです。 。 PostgreSQLがプリペアドステートメントを使用する場合、この推論は不可能です。その場合、可能な限りすべての可能なパラメータ値に対して機能する計画が作成されます。これはかもしれない (インデックスのために)ランダムアクセスを介してテーブル全体の大部分をフェッチすることは、単純な順次スキャンよりも遅いため、言及されたインデックスを除外します。 準備 docはこれを確認します:

    ところで-プランのキャッシュについては、準備 docにも言いたいことがあります:

    また、自動プランキャッシングや、複数の接続でのキャッシング/再利用はありません。

    例外 :私は「通常」言及しました。表示されているpsql 例は、PerlDBIのようなクライアントアダプタが実際に使用するものではありません。特定のプロトコル を使用します 。ここで、「単純なクエリ」という用語は、psqlの「準備されていないクエリ」に対応します。 、用語 "拡張クエリ 「」は「準備されたクエリ」に対応しますが、1つの例外があります。(1つの)「名前のないステートメント」と(場合によっては複数の)「名前の付いたステートメント」には違いがあります。名前付きステートメントに関しては、ドキュメント 言う:

    また:

    したがって、この場合、計画は、上記のPREPAREで説明したように、パラメーターなしで実行されます。 -新しいことは何もありません。

    言及された例外は「名前のないステートメント」です。ドキュメントによると:

    そして、ここに利点があります。名前のないステートメントは「準備済み」ですが(つまり、パラメーターを置き換えることができます)、クエリプランを実際のパラメーターに適合させることもできます。

    ところで:名前のないステートメントの正確な処理は、PostgreSQLサーバーの過去のリリースで数回変更されました。本当に必要な場合は、古いドキュメントで詳細を検索できます。

    根拠-Perl/任意のクライアント

    どのようにクライアント Perlがプロトコルを使用するように、まったく別の質問です。 Java用のJDBCドライバーのような一部のクライアントは、基本的に次のように述べています。プログラマーがプリペアドステートメントを使用する場合でも、最初の5つ(またはそれ以上)の実行は内部で「単純なクエリ」(つまり、実質的に準備されていない)にマップされ、その後、ドライバーは「名前付きステートメント」。

    したがって、クライアントには次の選択肢があります。

    • 「単純なクエリ」プロトコルを使用して、毎回(再)計画を強制します。
    • 計画 1回、「extendedquery」プロトコルと「namedstatement」を使用して複数回実行します(計画はパラメーターなしで行われるため、計画が不適切な場合があります)。
    • 解析 一度、「拡張クエリ」プロトコルと「名前のないステートメント」を使用し、さらにいくつかのことに従うことによって(現在のPostgreSQLバージョンで)各実行を計画します(「解析」メッセージ中にいくつかのパラメータを提供します)
    • JDBCドライバーのようなまったく異なるトリックをプレイします。

    Perlが現在行っていること:わかりません。しかし、言及された「赤いニシン」は非常にありそうもないことではありません。




    1. Python MySQLコネクタ:SSLでサーバーに接続できません

    2. SQLサーバーで数字を単語に変換できる組み込み関数はありますか

    3. SequelizeでSequelizeUniqueConstraintErrorを無視する方法は?

    4. GitHubアクション:GithHubアクションでPostgresに接続する方法