2

この質問はDBスタック交換サイトに適しているかもしれませんが、私にはわかりませんでした。

とにかく、私はクエリの最適化を扱っていますが、バインド変数を使用するとパーサーがそれほど難しくないことを学びました。実行中のクエリに改善が見られましたが、バインド変数用にソフトウェアから渡された静的変数を削除することも役立つかどうか疑問に思っています。次に例を示します。

select *
from report
where report.name = :1
and report.enabled = '1'

私はそれをサブアウトして言うことができます

select *
from report
where report.name = :1
and report.enabled = :2

私はただ変更を加えるだけですが、実際にソフトウェアでそれを行い、それがもたらす違いを確認するプロセスは、やや長くて退屈です。(最初の例のように)リテラルを混合すると、それらが常に同じであっても、オプティマイザーの効率が損なわれるかどうかを誰かが知っていますか?

前もって感謝します。

4

4 に答える 4

7

あなたが何を意味するI learned that using bind variables makes the parser not work as hardのか正確にはわかりませんが、私は推測します...


クライアントでSQL文字列を作成し、それらをOracleデータベースに送信して実行していますか?

その場合、クエリをパラメータ化するという行為は、DBエンジンが、パラメータは異なるものの、同じ実行プラン/説明プランを使用して複数のクエリを満たすことができることを確認できることを意味します。

これは、エンジンがネイティブSQLを再コンパイルする必要がなく、キャッシュにすでに(潜在的に)プランを再利用できることを意味します。

パラメータ化がなく、「name」の値が異なる場合、エンジンはクエリを完全に異なるものと見なし、類似性に気付かないでしょう。これにより、まったく同じ文字列がすでにキャッシュにない限り、SQLがコンパイルされます。


ただし、クエリに常にが含まれている場合report.enabled = 1は、クエリのその部分をパラメータ化する必要はありません。静的であるため、パラメーターを使用しないという行為によって、パラメーターが別のクエリのように見えることはなく、パラメーターが再コンパイルされることもありません。

逆に、インデックスやデータの統計などによっては、実際に節約できる場合があります。たとえば、データの99%が「有効= 1」の場合、データの1%とは異なるプランを取得する可能性があります。 「有効=1」であること。ただし、エンジンは、検索される値が常に1であることがわかっているクエリで、「enabled = 1」に対してのみ最適化されます。これは、静的に(リテラルとして)指定された場合にのみ当てはまります。


要するに、それが本当に静的な値である場合、それをパラメータ化しないでください。

于 2011-12-20T16:27:19.510 に答える
4

SQLに実際に定数が含まれている場合(つまり、句が常にである場合enabled=1)、SQLで定数をリテラルとして使用する理由はいくつかあります。

  • パフォーマンスの問題があり、バインドの値にすぐにアクセスできない場合(一部のトレースファイルなど)は、デバッグが簡単です。
  • オプティマイザーは、定数を使用する場合(つまり、バインドピークが無効になっている場合、または古いバージョンのDBMSの場合)、特にこの列にヒストグラムのある統計がある場合に、クエリのカーディナリティをより効率的に推定できる場合があります。
  • 特定のプランオプション(たとえば、パーティションの剪定)には定数を使用する必要があります

また、パフォーマンスの他に、パラメーター化されたクエリを使用するもう1つの主な理由は、SQLインジェクションを防ぐことです。真の定数は、外部ソースではなくコードによって提供されるため、SQLインジェクションの対象にはなりません。

于 2011-12-20T16:30:44.237 に答える
0

Oracle は SQL ステートメントを受け取ると、最初に SQL ステートメントとその実行計画が既にキャッシュに存在するかどうかを調べます。その場合、実行計画を再作成するコストが節約されるため、実行時間が節約されます。入ってくる SQl ステートメントがキャッシュ内のステートメントと一致するためには、完全に一致する必要があります (文字、バインド変数、および空白を含む)。そのため、変数の異なる値 (したがって異なるリテラル) に対してステートメントが同じままになるように、バインド変数を使用することをお勧めします。ただし、同じリテラルが常に使用されている場合は、バインド変数を使用しても違いはありません。解析と実行計画の生成に関して、パフォーマンスはどちらの場合も同じです。

于 2011-12-20T16:28:14.020 に答える
0

答えは、よくあることですが、「場合による」です。

何の上に?アプリケーションは OLTP (多くのクエリ、小さな結果セット) または DSS (少数のクエリ、大量のデータ) ですか? バインドからリテラルへの変更を検討している列に関連するスキューは何ですか? それらの列はバインド可能である必要がありますか、それとも常に同じ値にバインドされていますか?

于 2011-12-20T16:22:27.800 に答える