114

従来の知識では、ストアドプロシージャの方が常に高速であるとされています。したがって、それらは常に高速であるため、常に使用してください

私はこれがかつてそうであったいくつかの歴史的文脈に基づいているとかなり確信しています。さて、私はストアドプロシージャが必要ないことを主張していませんが、MySQL、SQL Server、Oracle、または< Insert_your_DB_here >などの最新のデータベースでストアドプロシージャが必要な場合を知りたいと思います。ストアドプロシージャを介してすべてのアクセス権を持つのはやり過ぎですか?

4

20 に答える 20

267

これは、特定の 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 を使用していれば、アドホック プロシージャとストアド プロシージャの違いに気付かないと思います。

于 2008-09-12T20:53:57.390 に答える
29

ストアド プロシージャを使用する理由:

  • ネットワーク トラフィックを減らします。ネットワーク経由で SQL ステートメントを送信する必要があります。sprocs を使用すると、SQL をバッチで実行できるため、効率も向上します。
  • クエリ プランのキャッシュ-- sproc が初めて実行されるときに、SQL Server は実行プランを作成し、再利用のためにキャッシュします。これは、頻繁に実行される小さなクエリで特にパフォーマンスが向上します。
  • 出力パラメーターを使用する機能-- 1 行を返すインライン SQL を送信した場合、レコードセットのみを取得できます。sprocs を使用すると、それらを出力パラメーターとして戻すことができます。これはかなり高速です。
  • パーミッション-- インライン SQL を送信する場合、テーブルに対するパーミッションをユーザーに付与する必要があります。これにより、単に sproc を実行するパーミッションを付与するよりもはるかに多くのアクセスが付与されます。
  • ロジックの分離-- SQL 生成コードを削除し、データベース内で分離します。
  • 再コンパイルせずに編集する機能-- これは物議を醸す可能性があります。アプリケーションを再コンパイルしなくても、sproc で SQL を編集できます。
  • テーブルが使用されている場所を検索します。特定のテーブルを参照しているすべての SQL ステートメントを検索する場合は、sprocs を使用して、sproc コードをエクスポートして検索できます。これは、コードで検索するよりもはるかに簡単です。
  • 最適化-- sproc を使用すると、DBA が SQL を最適化し、データベースを調整するのが容易になります。欠落しているインデックスなどを見つけやすくなります。
  • SQL インジェクション攻撃-- 適切に記述されたインライン SQL は攻撃を防御できますが、この防御には sproc の方が優れています。
于 2008-10-16T15:36:27.980 に答える
21

多くの場合、ストアドプロシージャはより一般化されているため、実際には低速です。ストアドプロシージャは高度に調整できますが、私の経験では、十分な開発と制度上の摩擦があり、一度機能するとそのままにしておくことができます。そのため、ストアドプロシージャは、「万が一に備えて」多くの列を返す傾向があります。アプリケーションを変更するたびに新しいストアドプロシージャをデプロイする必要があります。一方、OR / Mは、アプリケーションが使用している列のみを要求します。これにより、ネットワークトラフィック、不要な参加などが削減されます。

于 2008-09-12T20:38:25.663 に答える
9

それはどんどん激怒する議論です(例えば、ここで)。

アプリに不正なデータアクセスロジックを記述するのと同じくらい、不正なストアドプロシージャを記述するのは簡単です。

私の好みはストアドプロシージャですが、それは通常、データベースサーバーの正常な実行を維持する責任を負う専用のDBAがいるエンタープライズ環境で非常に大規模で複雑なアプリを使用しているためです。

他の状況では、LINQなどのデータアクセステクノロジが最適化を処理できることを嬉しく思います。

ただし、考慮事項は純粋なパフォーマンスだけではありません。通常、セキュリティや構成管理などの側面は、少なくとも同じくらい重要です。

編集:Frans Boumaの記事は確かに冗長ですが、セキュリティに関するポイントを1マイルも見逃しています。それが5歳であるという事実も、その関連性を助けません。

于 2008-09-12T20:41:20.133 に答える
9

データベースはこれらのクエリの実行計画もキャッシュするため、ほとんどの最新のデータベースでは、ストアド プロシージャとパラメーター化されたクエリまたは準備されたクエリの速度に顕著な違いはありません。

パラメータ化されたクエリはアドホック SQL と同じではないことに注意してください。

今日でもいまだにストアド プロシージャを支持する主な理由は、セキュリティに関係しています。ストアド プロシージャのみを使用する場合は、アプリケーションのユーザーの INSERT、SELECT、UPDATE、DELETE、ALTER、DROP、CREATE などのアクセス許可を無効にして、EXECUTE のみを残すことができます。

これにより、 2 次SQL インジェクションに対する保護が少し強化されます。パラメータ化されたクエリは、一次インジェクションからのみ保護します。

于 2008-09-12T20:50:34.730 に答える
5

明らかに、実際のパフォーマンスは個々のケースで測定されるべきであり、仮定されるべきではありません. ただし、ストアドプロシージャによってパフォーマンスが低下する場合でも、ストアド プロシージャを使用する十分な理由があります。

  1. アプリケーション開発者は、常に最高の SQL コーダーであるとは限りません。ストアド プロシージャは、SQL をアプリケーションから隠します。

  2. ストアド プロシージャは自動的にバインド変数を使用します。アプリケーション開発者は、バインド変数が不要なコードのように見え、小規模なテスト システムではほとんどメリットがないため、バインド変数を避けることがよくあります。後で、バインド変数の使用に失敗すると、RDBMS のパフォーマンスが低下する可能性があります。

  3. ストアド プロシージャは、後で役立つ可能性のある間接的なレイヤーを作成します。アプリケーション コードに手を加えることなく、データベース側で実装の詳細 (テーブル構造を含む) を変更することができます。

  4. ストアド プロシージャを作成する作業は、システムのすべてのデータベース対話を文書化するのに役立ちます。また、状況が変化したときにドキュメントを更新する方が簡単です。

そうは言っても、私は通常、自分で制御できるように生の SQL をアプリケーションに貼り付けています。それは開発チームと哲学に依存します。

于 2008-09-12T20:51:06.583 に答える
5

ストアド プロシージャの利点としてまだ誰も言及していないトピックの 1 つは、セキュリティです。ストアド プロシージャを介したデータ アクセスのみを使用してアプリケーションを構築する場合は、データベースをロックダウンして、それらのストアド プロシージャを介したアクセスのみにすることができます。そのため、誰かがデータベース ID とパスワードを取得したとしても、そのデータベースに対して表示または実行できることは制限されます。

于 2008-09-13T14:59:28.950 に答える
4

2007 年には、ORM 経由で MS SQL Server を使用するプロジェクトに参加していました。SQL Server で最大 7 ~ 8 秒の読み込み時間を要した 2 つの大きく成長しているテーブルがありました。2 つの大きなストアド SQL プロシージャを作成し、クエリ プランナーからそれらを最適化した後、各 DB ロード時間は 20 ミリ秒未満に短縮されました。したがって、ストアド SQL プロシージャを使用する効率的な理由がまだ残っていることは明らかです。

そうは言っても、ストアド プロシージャの最も重要な利点は、メンテナンスの容易さ、セキュリティ、データの整合性、およびビジネス ロジックをミドルウェア ロジックから切り離すことであり、2 つのプロシージャの再利用によってすべてのミドルウェア ロジックに利点があることがわかりました。 .

私たちの ORM ベンダーは、多くの小さな SQL クエリを実行する方が、結合された大きなデータ セットを取得するよりも効率的であるといつも主張していました。私たちの経験は(驚いたことに)別のことを示しました。

もちろん、これはマシン、ネットワーク、オペレーティング システム、SQL サーバー、アプリケーション フレームワーク、ORM フレームワーク、および言語の実装によって異なる可能性があるため、他のことを行うことで得られる可能性があると思われる利点を測定してください。

ORM とすべての負荷を処理するデータベースとの間に問題があることを発見したのは、ベンチマークを行うまではありませんでした。

于 2009-11-25T14:55:48.353 に答える
3

SP を使用することが理にかなっている場合は、SP を使用することを好みます。いずれにせよ、SQL Server では、パラメータ化されたクエリよりも SP にパフォーマンス上の利点はありません。

しかし、私の現在の仕事では、顧客が SP を必要とするため、SP を使用せざるを得ないと上司が言いました。彼らはより安全だと感じています。ロールベースのセキュリティを実装しているかどうかを確認するのに十分な時間はここにいませんが、実装していると感じています.

したがって、この場合、顧客の感情は他のすべての議論に勝ります。

于 2008-09-12T20:45:03.870 に答える
2

私にとってストアド プロシージャの利点の 1 つは、ホスト言語にとらわれないことです。コードを書き直すことなく、C、Python、PHP などのアプリケーションから別のプログラミング言語に切り替えることができます。さらに、一括操作などの一部の機能は実際のパフォーマンスを向上させますが、ホスト言語では簡単に利用できません (まったく利用できませんか?)。

于 2011-10-11T16:20:18.690 に答える
1

彼らが速いかどうかはわかりません。私はデータアクセスにORMを使用するのが好きです(車輪の再発明をしないため)が、それが常に実行可能なオプションであるとは限らないことを理解しています。

Frans Boumaには、このテーマに関する優れた記事があります:http ://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx

于 2008-09-12T20:34:44.517 に答える
1

その上でFransBoumaの優れた投稿(少し偏っている場合)を読んでください。

于 2008-09-12T20:35:26.030 に答える
1

私が話すことができるのはSQLサーバーだけです。そのプラットフォームでは、サーバーが実行プランを格納するため、ストアドプロシージャは優れています。これにより、ほとんどの場合、パフォーマンスが大幅に向上します。SPの実行パスが大きく異なる場合、パフォーマンスが最適化されない可能性があるため、「ほとんどの場合」と言います。ただし、そのような場合でも、SPのいくつかの啓発されたリファクタリングは物事をスピードアップすることができます。

于 2008-09-12T20:39:05.460 に答える
1

これを理解することは質問のトピックから少し外れていますが、多くのストアド プロシージャを使用している場合は、それらをある種のソース管理 (Subversion や git など) の下に置く一貫した方法があることを確認し、次のことができるようにします。更新プログラムを開発システムからテスト システム、さらに運用システムに移行します。

これが手作業で行われると、どのコードがどこにあるかを簡単に監査する方法がなく、すぐに悪夢になります。

于 2008-09-13T14:51:53.210 に答える
1

CRUD 操作にストアド プロシージャを使用するのはおそらくやり過ぎですが、使用するツールとユーザーの好み (または要件) によって異なります。私はインライン SQL を好みますが、パラメーター化されたクエリを使用して SQL インジェクション攻撃を防ぐようにしています。注意しないと何がうまくいかないかを思い出させるために、このxkcd コミックを印刷しておきます。

ストアド プロシージャは、複数のデータ セットを操作して 1 つのデータ セットを返す場合に、実際のパフォーマンスを向上させることができます。通常、データ セットをネットワーク経由で送信してクライアント エンドで処理するよりも、ストアド プロシージャでデータ セットを処理する方が効率的です。

于 2008-09-12T21:01:47.883 に答える
0

ストアドプロシージャは、データベースがトークン化してメモリに格納するため、SQLコードが頻繁に実行される場合に最適です。ストアドプロシージャの外部で同じコードを繰り返し実行すると、同じコードを何度も再解析するデータベースからパフォーマンスが低下する可能性があります。

私は通常、コードをストアドプロシージャまたはSqlCommand(.NET)オブジェクトとして頻繁に呼び出し、必要な回数だけ実行します。

于 2008-09-12T20:34:57.450 に答える
0

私見では...

「C_UD」操作をストアド プロシージャに制限すると、データ整合性ロジックを 1 か所に保持できます。これは、「C_UD」操作を単一のミドルウェア層に制限することによっても実行できます。

アプリケーションに読み取り操作を提供できるため、必要なテーブル/列のみを結合できます。

于 2008-09-13T16:03:53.990 に答える
0

はい、ほとんどの場合、高速です。SQL の構成も、大きなパフォーマンス チューニング領域です。私がバック オフィス タイプのアプリを実行している場合、それらをスキップすることがありますが、他の人が話したすべての理由、つまりセキュリティのために、本番環境に直面しているものはすべて確実に使用します。

于 2008-09-12T21:03:08.223 に答える
0

ストアド プロシージャは、パラメーター化されたクエリ (またはアドホック クエリ) の代わりに使用することもでき、他の利点もあります。

  • 何かを修正する必要がある場合 (並べ替え順序など)、アプリを再コンパイルする必要はありません。
  • そのユーザー アカウントのすべてのテーブルへのアクセスを拒否し、ストアド プロシージャへのアクセスのみを許可し、ストアド プロシージャを介してすべてのアクセスをルーティングすることができます。このようにして、テーブルの制約よりもはるかに柔軟に、すべての入力のカスタム検証を行うことができます。
于 2008-09-13T22:50:34.213 に答える
-1

ネットワーク トラフィックの減少 -- SP は通常、動的 SQL よりも劣っています。選択ごとに新しい SP を作成するわけではないため、必要な列が 1 つだけの場合は、必要な列を含む SP を使用し、残りは無視するように指示されます。余分な列を取得し、ネットワークの使用量を減らしてください。また、SP を使用すると、多くのクライアント フィルタリングが発生する傾向があります。

キャッシュ -- MS-SQL は、MS-SQL 2000 が 7 だった可能性があるため、それらをまったく異なる方法で処理しませんが、覚えていません。

アクセス権 -- 私が行うほとんどすべてが Web であるか、すべてのデータベース アクセスを行う中間アプリケーション層があるため、問題ありません。クライアントからデータベースに直接アクセスできる唯一のソフトウェアは、ユーザーが直接アクセスできるように設計されており、ユーザーにアクセス許可を与えることに基づいているサードパーティ製品です。はい、MS-SQL パーミッション セキュリティ モデルは最低です!!! (2008 年にはまだ時間をかけていません) これの最後の部分として、直接のクライアント/サーバー プログラミングと Web および中間アプリケーション サーバー プログラミングをまだ行っている人の数を調査したいと思います。彼らが大規模なプロジェクトを行っているのであれば、なぜ ORM がないのでしょうか。

分離 -- ビジネス ロジックを中間層の外に置く理由を疑問視する人がいます。また、データ処理コードを分離しようとしている場合は、データベースに配置せずにそれを行う方法があります。

編集する能力 -- 心配しなければならないテストやバージョン管理がないことはありますか? また、クライアント/サーバーにのみ問題があり、Web の世界では問題ありません。

テーブルを見つける -- それを使用する SP を特定できる場合にのみ、バージョン管理システム、エージェント ランサック、またはビジュアル スタジオのツールを使用して検索します。

最適化 -- DBA はデータベースのツールを使用して、最適化が必要なクエリを見つける必要があります。データベースは、どのステートメントが最も時間とリソースを消費しているかを DBA に伝えることができ、そこから修正できます。複雑な SQL ステートメントの場合、単純な選択で問題がなければ、DBA に相談するようにプログラマーに指示する必要があります。

SQL インジェクション攻撃 -- SP はこれ以上の保護を提供しません。彼らがうなずく唯一のことは、彼らのほとんどがパラメーターを使用して教えているのに対し、動的SQLのほとんどの例はパラメーターを無視していることです。

于 2008-10-24T16:44:32.727 に答える