これは、特定の DBMS に規制されていないストアド プロシージャの一般的な見方であることに注意してください。一部の DBMS (さらには、同じ DBMS の異なるバージョン!) はこれに反して動作する可能性があるため、これがすべて有効であると想定する前に、対象の DBMS を再確認する必要があります。
私は、ほぼ 10 年間 (C、PHP、PL/SQL、C#.NET、および Ruby でのアプリケーション開発と共に)、Sybase ASE、MySQL、および SQL Server DBA をオンとオフを繰り返してきました。だから、私はこの(時々)聖戦で粉砕する特定の斧を持っていません.
ストアド プロシージャのこれまでのパフォーマンス上の利点は、一般的に次のとおりです (順不同)。
- 事前に解析された SQL
- 事前に生成されたクエリ実行プラン
- ネットワーク待ち時間の短縮
- 潜在的なキャッシュの利点
事前に解析された SQL -- 非常にミクロなレベルを除いて、コンパイルされたコードと解釈されたコードと同様の利点があります。
それでも有利?
最新の CPU ではあまり目立ちませんが、非常に大きな 1 つの SQL ステートメントを 1 秒間に 1,100 億回送信している場合、解析のオーバーヘッドが増える可能性があります。
事前生成されたクエリ実行プラン。多くの JOIN がある場合、順列は非常に扱いにくくなる可能性があります (最新のオプティマイザーには、パフォーマンス上の理由から制限とカットオフがあります)。非常に複雑な SQL では、オプティマイザーが「最適に近い」を見つけようとするため、明確で測定可能な (DBMS を微調整する前に、複雑なクエリがプランを生成するだけで 10 秒以上かかるのを見たことがあります) レイテンシーを持つことはよく知られています。 " 実行計画。通常、ストアド プロシージャはこれをメモリに格納するため、このオーバーヘッドを回避できます。
それでも有利?
ほとんどの DBMS (最新版) は、INDIVIDUAL SQL ステートメントのクエリ プランをキャッシュし、ストアド プロシージャとアドホック SQL の間のパフォーマンスの差を大幅に削減します。これに当てはまらないいくつかの注意事項とケースがあるため、ターゲット DBMS でテストする必要があります。
また、ますます多くの DBMS では、オプティマイザ パス プラン (抽象クエリ プラン) を提供して、最適化時間を大幅に短縮できます (アドホック SQL とストアド プロシージャ SQL の両方!!)。
警告キャッシュされたクエリ プランは、パフォーマンスの万能薬ではありません。生成されるクエリ プランが最適でない場合があります。たとえば、 を送信するSELECT *
FROM table WHERE id BETWEEN 1 AND
99999999
と、DBMS はインデックス スキャンではなくフル テーブル スキャンを選択する可能性があります。これは、テーブル内のすべての行を取得しているためです (統計によるとそうです)。これがキャッシュされたバージョンの場合、後で を送信したときにパフォーマンスが低下する可能性があります
SELECT * FROM table WHERE id BETWEEN
1 AND 2
。この背後にある理由は、この投稿の範囲外ですが、詳細については、http:
//www.microsoft.com/technet/prodtechnol/sql/2005/frcqupln.mspx
および
http://msdn.microsoft.com/を参照してください。 en-us/library/ms181055.aspx
およびhttp://www.simple-talk.com/sql/performance/execution-plan-basics/
「要約すると、彼らは、コンパイルまたは再コンパイルが実行されたときに共通の値以外のものを提供すると、オプティマイザーがその特定の値のクエリプランをコンパイルおよびキャッシュすることになると判断しました。共通の値 ('M'、'R'、または 'T') のクエリを実行すると、最適なパフォーマンスが得られませんでした。この最適化されていないパフォーマンスの問題は、クエリが再コンパイルされるまで存在していました。その時点で、@P1 に基づいてパラメータ値が指定されていない場合、クエリにパフォーマンスの問題がある場合とない場合があります。」
ネットワーク待ち時間の短縮
A) 同じ SQL を何度も実行していて、SQL のコードが何 KB にも上る場合、それを単純な「exec foobar」に置き換えると、実際に合計される可能性があります。B) ストアド プロシージャを使用して、手続き型コードを DBMS に移動できます。これにより、大量のデータをクライアントにシャッフルする必要がなくなり、情報が少しずつ返されます (またはまったく返されません!)。DBMS とコードで JOIN を実行するのと似ています (みんなのお気に入りの WTF!)。
それでも有利?
A) 最新の 1Gb (および 10Gb 以上!) イーサネットでは、これは実際には無視できます。B) ネットワークがどれだけ飽和しているかにもよりますが、正当な理由もなく数メガバイトのデータをやり取りするのはなぜでしょうか?
潜在的なキャッシュの利点
DBMS に十分なメモリがあり、必要なデータがサーバーのメモリにある場合、データのサーバー側変換の実行が高速になる可能性があります。
それでも有利?
アプリが DBMS データへのメモリ アクセスを共有していない限り、エッジは常にストアド プロシージャになります。
もちろん、ストアド プロシージャの最適化についての議論は、パラメータ化されたアドホック SQL についての議論なしには完結しません。
パラメーター化/プリペアド SQL
ストアド プロシージャとアドホック SQL のクロスのようなもので、クエリ値に「パラメーター」を使用するホスト言語に埋め込まれた SQL ステートメントです。
SELECT .. FROM yourtable WHERE foo = ? AND bar = ?
これらは、最新のオプティマイザーがクエリ実行プランをキャッシュ (および再利用) するために使用できるクエリのより一般化されたバージョンを提供し、ストアド プロシージャのパフォーマンス上のメリットの多くをもたらします。
アドホック SQL
DBMS のコンソール ウィンドウを開いて、SQL ステートメントを入力するだけです。以前は、DBMS にはパラメータ化/ストアド プロシージャのようにクエリを事前に最適化する方法がなかったため、これらは (平均して) 「最悪」のパフォーマンスでした。
それでもデメリット?
必ずしも。ほとんどの DBMS には、アドホック SQL をパラメーター化されたバージョンに "抽象化" する機能があります。したがって、2 つの違いはほとんどなくなります。これを暗黙的に行うものや、コマンド設定で有効にする必要があるものもあります (SQL サーバー: http://msdn.microsoft.com/en-us/library/ms175037.aspx、Oracle: http://www.praetoriate.com/oracle_tips_cursor_sharing. htm )。
学んだ教訓?
ムーアの法則は前進し続けており、DBMS オプティマイザーはリリースごとにより洗練されています。確かに、すべてのばかげた小さな SQL ステートメントをストアド プロシージャ内に配置することはできますが、オプティマイザーに取り組んでいるプログラマーは非常に頭が良く、パフォーマンスを改善する方法を絶えず探していることを知っておいてください。最終的に (まだここにない場合) アドホック SQL のパフォーマンスは、ストアド プロシージャのパフォーマンスと (平均して!) 見分けがつかなくなるため、あらゆる種類の大規模なストアド プロシージャは ** "パフォーマンス上の理由" だけで ** 使用するのは時期尚早の最適化のように思えます。 .
とにかく、極端なケースを避け、ごく普通の SQL を使用していれば、アドホック プロシージャとストアド プロシージャの違いに気付かないと思います。