2012-02-08 24 views
1

一見すると、SQLPrepare + SQLBindParameter + SQLExecuteをフォーマット文字列(例:CString::Format)よりも使用し、完全なクエリ文字列全体をSQLExecDirectに渡す方が効率的であるようです。そうでない場合、なぜ2番目の方法(SQLPrepare + SQLBindParameter + SQLExecute)が存在するのでしょうか?SQLExecDirectをSQLPrepare + SQLBindParameter + SQLExecuteの代わりに書式設定済みのクエリ文字列と併用するのは悪い考えですか?

しかし、ここに私の考えがあります:ドライバーは遅かれ早かれ(私は後で、とにかく...)パラメータを変換する(私はそれをSQLBindParameterで)文字列表現に変換しますか? (またはそうでないかもしれません)私のアプリケーション(printfのような書式設定)でこの書式を設定すると、パフォーマンスが低下しますか?

ネットワーク経由で接続されているときに、パラメータを生データとして渡してサーバー側でフォーマットすると、事前にフォーマットされたクエリ文字列を渡す代わりにネットワークトラフィックが減少する可能性があります。瞬間。そうでない場合は、アプリケーションで完全なクエリ文字列をフォーマットしてからSQLExecDirectを使用する代わりに、SQLPrepare + SQLBindParameter + SQLExecuteを使用するとパフォーマンスが向上しますか?

私にとってSQLExecDirectを使用すると、より簡単で便利なので、私は別のアプローチを選択する必要があるかどうかについて(そしてもしあれば)良い答えが必要です。

重要:あなたはSQLPrepare + SQLBindParameter + SQLExecuteアプローチは、より良い性能を与えることを言うだろうならば、私はどのくらいを知りたいです!私は理論的な前提を気にしない、実際にはいつ価値があるのか​​知りたいのですが?私の現在のユースケースはあまりDB集約的ではありませんが、1秒あたり100個以上の挿入/更新はありません。SQLExecDirectを使用してもよろしいですか?どのようなシナリオがありますか - それが今までなら、私はSQLPrepare + SQLBindParameter + SQLExecuteを使用する必要がありますか?

+0

を**ありませんそうではありません...バインディングはシンプルであればクエリは短く、あなたが何をしているのかを知っている**特に、数字を含む短いもの(例えば、 'select * from table where id =#;')*。ドグマ*(以下の回答)*を無視して頭を使ってください。 :) – CodeAngry

答えて

2

同じSQL(パラメータを除く)を繰り返し挿入または更新する場合、SQLPrepare、SQLBindParameterおよびSQLExecuteは毎回SQLExecDirectより高速になります。考えてみましょう:

SQLPrepare("insert into mytable (cola, colb) values(?,?);"); 
for (n = 0; n < 10000; n++) { 
    SQLBindParameter(1, n); 
    SQLBindParameter(2, n); 
    SQLExecute; 
} 

と最初の例で

for (n = 0; n < 10000; n++) { 
    char sql[1000]; 
    sprintf("insert into mytable (cola, colb) values(%d,%d)", n, n); 
    SQLExecDirect(sql); 
} 

を、文は一度準備されるので、DBエンジンは一度だけそれを解析し、一度実行計画をうまくしなければなりません。 2番目の例では、SQLとパラメータが毎回渡され、毎回SQLが異なるように見えるので、毎回解析されます。

さらに、最初の例では、パラメータの配列を使用して、複数のパラメータ行を1つのSQL_PARAMSET_SIZEで渡すことができます。

3.1.2 Inserting dataを参照してください。また、保存できる時間の表示もあります。

ネットワークトラフィックを無視すると、ドライバのボンネットの下で何が起こっているかを推測するだけです。

追加: ドライバが文字列に変換すると思うように見えるパラメータで何が起こるかについてのあなたの説明については、パラメータをバインドすることのもう1つの利点は、1つのタイプでそれらを提供し、別のタイプとしてそれらを使用するようにドライバに要求することです。パラメータで避けることのできる何らかの変換関数を追加することなく、文字列として簡単に表現できないパラメータ型を見つけることができます。

+0

いいえいいえいいえ...私はSQLExecDirectを複数回実行しているわけではありません。 sprintfをループ内で使用して値の部分を書式設定し、ステートメント部分(「mytable(cola、colb)の値に挿入...」)に追加してから、単一のSQLExecDirect呼び出しに渡すことができます。 –

+0

あなたは「そうでなければ、なぜ2番目の方法が存在するのだろうか」と言っています。私はそれの使用例を指摘しました。一度SQLExecDirectを呼び出すだけでは、それほど比較する必要はありません。 – bohica

+0

は、パラメータを使用する別の理由を追加するために私の答えを更新 – bohica

1

はい、それは悪いアイデアだし、二つの理由:

  1. パフォーマンス

    のSQLPrepareが解析するSQL文を引き起こし、SQLステートメントに応じて、それは時間がかかります。別のサーバーでDBを使用している場合は、DBを解析して送信する可能性があります。たとえ解析にだけ時間がかかる場合でも。クエリ全体を実行する時間が10%あれば、その文を2回実行するときにその時間を節約できます。これは、複数の行を挿入する場合や、別の時間を「選択」する場合などです。

    もちろん、渡されるSQL文は常に静的な文字列でなければなりません。一部のSQLフレームワークでは、準備された文キャッシュが用意されている場合もあります。私はODBCがこれを行うかどうかわかりません。実際の業績数値が必要な場合は、自分で測定する必要があります。すべてのクエリが異なります(テーブルの内容によっても異なる場合があります)。

  2. SQLインジェクション

    どんなにデータは、あなたがたCString ::フォーマットまたは他の方法でフォーマットしていることから来てどこが言う

    、あなたはSQLインジェクションのリスクがあるかもしれません。ソースからの文字列を使用していても、後であなたや他の人が外部からのデータを受け入れるようにコードを変更することがあり、SQLインジェクションに脆弱です。あなたはSQLインジェクションについての詳細情報が必要な場合は、単にStackOverflowの検索、私はそれについていくつかの良い質問があると確信している、またはこの画像を参照してください。http://xkcd.com/327/

+0

SQLインジェクションは良い点です。しかし、最初の部分で何を意味しているのかを完全には知ることはできません(「文を2回実行するときにその時間を節約する」と言うとき)。 ** bohica **が言ったことを意味するなら、彼の返信に私のコメントを見てください。 –

+0

「パフォーマンス」の段落を更新して、このステートメントを2回実行する意味を明確にしました。 – vividos

関連する問題