1

私は 20 年の SQL の経験がありますが、特に Oracle ではありません。「Oracle の専門家」は、パラメーターなしで SQL クエリを作成することを保証します (次のように)。

SELECT t.ID, t.Name, t.Address ... FROM Table1 t WHERE t.ID = 'someID' AND t.Name = 'someName'...

少なくともパラメータを使用するのと同じくらい高速です(このように)

SELECT t.ID, t.Name, t.Address ... FROM Table1 t WHERE t.ID = ? AND t.Name = ?

コードはループで実行されます。

私が経験した他のほとんどのデータベースでは、パラメーターを使用すると速度が向上します。データベースは、SQL ステートメントに一致するコンパイル済みプランをキャッシュできます。SQL は呼び出しごとに変更されないため (パラメーターは変更されますが)、これによりパフォーマンスが向上します。データベースは単にパラメーターをバインドして続行します。

「オラクルの専門家」は、これは必要ないと述べています。しかし、明らかに、Oracle はパラメーターを「解析」し、残りの文字列をキャッシュされた実行計画に一致させてから、最初にパラメーターとして渡されたかのようにパラメーターを再バインドする必要があります。

ここで正しい心像を持っていますか?パラメータの受け渡し/SQL構築戦略にどのようにアプローチするかが実際に違いを生まないという、Oracleについての「魔法のような」ものはありますか?

Java / JDBC / Oracle シン ドライバーについて、私が気付いていない、ここで知っておくべき考えはありますか?

理解を深めるか、知識を広げたいと思っています。

(セキュリティ上の懸念はさておき、SQL 文字列を作成すると SQL インジェクション攻撃が可能になることを理解しています。専門家の意見に対抗するためのより直接的な弾薬を探しています - 存在する場合)。

その他の詳細:Oracle 11gR2, Java 1.6

4

4 に答える 4

4

率直に言って、あなたはそれを正しく理解しており、Oracleの専門家はまったく専門家ではないようです(アプリケーションを本番環境に導入した後、アプリケーションを高速化するために高価なコンサルティング時間を売りたい場合を除きます)。

パラメータなしでSQLステートメントを作成する場合(Oracleではバインド変数と呼ばれます)、実行されるたびにデータベースにステートメントを強制的に解析させます。

より良い説明については、ソフト/ハード解析およびバインド変数に関するAskTomを参照してください。

于 2012-10-15T13:44:55.653 に答える
3

ほとんどの場合、パラメーターを使用することをお勧めします。リテラル (バージョン 1) を使用すると、わずかに異なる数千の SQL ステートメントがデータベースにヒットし、ハード パースが発生して、Oracle のステートメント キャッシュがいっぱいになります。

ルールの 1 つの例外を次に示します。値の分布が非常に不均一な列に対してクエリを実行している場合、リテラルを含むバージョンを使用すると、クエリ オプティマイザーがより適切なプランを見つけることができる場合があります。

例えば、スラッシュドット読者の圧倒的多数が男性(※)だとすると、

select * from slashdot_readers where gender='MALE';

クエリ オプティマイザーがインデックスを無視し、gender代わりにフル テーブル スキャンを実行する可能性があります。

select * from slashdot_readers where gender='FEMALE';

インデックスを使用する可能性があります。変数を使用すると、クエリ オプティマイザーは使用するバージョンがわからないため、常にフル テーブル スキャンを実行する可能性があります。

(*) この例のためだけに

于 2012-10-15T13:49:52.963 に答える
1

パフォーマンスの測定は行っていませんが、あなたの写真は正しいと思います。いずれにせよ、それらが同等に高速であっても、SQLインジェクションを防ぐために、パラメーター/バインド変数を使用するバリアントを常に好むでしょう。where句に文字列を修正したサンプルでは、​​これは問題にならないかもしれませんが、実際のアプリケーションでは、これらの文字列は通常、外部から取得されます。(私がこの答えを書いたときにあなたはあなたの質問を編集したと思います:-))

于 2012-10-15T13:41:56.203 に答える
1

測定を行います。データを取得します。

オラクルについて私が知っているすべてから、あなたは正しいはずです。明らかに、ループ内にあるかどうかを確認して、同じものを再実行し、PreparedStatement毎回再準備しないようにしてください。それだけで、クエリのコストを削減できます。

注意すべき点の 1 つ - 実際のアプリケーションでは、単純なテスト ケースよりもバインド変数を使用することでさらに多くのメリットが得られる可能性があります。実際のアプリケーションでは、Oracle のキャッシュにはあらゆる種類の他の SQL ステートメントが含まれているためです (さまざまなメモリ領域の用語を忘れてしまいました)。現時点では Oracle にキャッシュされています)、それがいっぱいになると、常に新しい SQL を送信するコストがかなり高くなります。

于 2012-10-15T14:03:51.537 に答える