[解決済み] ストアドプロシージャは、一般的に、最新のRDBMSのインラインステートメントよりも効率的ですか?重複] [重複] [重複
質問
従来の常識では、ストアドプロシージャは常に高速であると言われています。だから、ストアドプロシージャは常に速いので、それを使いましょう。 常に .
これは、かつてそうであった何らかの歴史的な文脈に基づくものであることは間違いありません。さて、私はストアド プロシージャが不要であると主張しているわけではありませんが、MySQL、SQL Server、Oracle、または < などの現代のデータベースでストアド プロシージャがどのような場合に必要であるかを知りたいのです。 挿入_your_DB_here などで必要なのか知りたいです。ストアドプロシージャですべてのアクセスを行うのはやりすぎでしょうか?
どのように解決するのですか?
<ブロッククオート注意 これはストアドプロシージャの一般的な見方であり、特定の DBMS に規制されていない一般的なものであることに注意してください。いくつかのDBMS(さらには、同じDBMSの異なるバージョン!)は 同じDBMSの異なるバージョンでさえも!)、これに反して動作することがあります。 あるDBMS(さらには同じDBMSの異なるバージョン!)はこれに反して動作する場合があります。 対象となるDBMSで再確認してください。 で再確認してください。
私は、ほぼ 10 年間、Sybase ASE、MySQL、および SQL Server の DBA をオンとオフでやってきました (C, PHP, PL/SQL, C#.NET および Ruby によるアプリケーション開発と共に)。そのため、この (時には) 聖戦において、私は特に対立軸を持ちません。
ストアド プロックの歴史的なパフォーマンスの利点は、一般に次のようなものでした (順不同)。
- 事前に解析された SQL
- 事前に生成されたクエリ実行計画
- ネットワーク遅延の低減
- キャッシュの潜在的な利点
プリパースされたSQL
非常にミクロなレベルを除いて、コンパイルされたコードと解釈されたコードに類似した利点があります。
まだ利点がありますか?
それでも有利ですか? しかし、非常に大きな SQL 文を 1 秒間に 1100 億回送信する場合、解析のオーバーヘッドが増加する可能性があります。
事前に生成されたクエリ実行計画 . 多くの JOIN がある場合、順列は非常に手に負えないほど大きくなる可能性があります (最近のオプティマイザには、パフォーマンス上の理由から制限とカットオフがあります)。非常に複雑なSQLの場合、オプティマイザが最適に近い実行計画を見つけようとするため、はっきりとした測定可能な遅延(DBMSを調整する前に、複雑なクエリが計画を生成するためだけに10秒以上かかるのを見たことがあります)が発生することも珍しくありません。ストアドプロシージャは、一般に、これをメモリに保存するので、このオーバーヘッドを回避することができます。
それでもまだ利点がありますか?
まだ利点がありますか? ほとんどの DBMS (最新版) は、個々の SQL 文のクエリプランをキャッシュし、ストアドプロックとアドホック SQL の間の性能差を大幅に削減します。これが適用されないいくつかの注意事項やケースがあるので、ターゲット DBMS でテストする必要があります。
また、オプティマイザのパスプラン(抽象的なクエリプラン)を提供して、最適化の時間を大幅に短縮できるDBMSも増えています(アドホックとストアドプロシージャの両方の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')に対して同じクエリを実行する際に (のクエリプランを再利用した場合、そのクエリプランは最適とは言えない結果となりました。 最適とは言えない性能となりました。この この最適でない性能の問題 は、クエリを再コンパイルするまで存在しました。 再コンパイルされるまで存在しました。その時点では パラメータ値に基づいて クエリにパフォーマンスの問題があるかどうかは パフォーマンスの問題があるかもしれません。
ネットワーク遅延の低減 A) 同じ SQL を何度も何度も実行している場合、そしてその SQL が何 KB ものコードになる場合、それを単純な "exec foobar" に置き換えることは、本当に大きな負担となります。 B) ストアドプロックは、手続き的なコードをDBMSに移動させるために使うことができます。これは、大量のデータをクライアントに送り、クライアントから情報を少しずつ(または全く)送り返すという作業を省くことができます。コード内ではなくDBMS内でJOINを行うことに似ています(みんな大好きなWTF!)。
それでもまだ利点がありますか?
A) 最近の 1Gb (そして 10Gb 以上!) イーサネットでは、これは本当に無視できるほど小さくなります。 B) ネットワークがどの程度飽和しているかによりますが、数メガバイトのデータを無意味に前後に押し出す必要はないでしょう?キャッシュの潜在的な利点
キャッシュの潜在的な利点 DBMSに十分なメモリがあり、必要なデータがサーバのメモリにある場合、データのサーバサイド変換を実行すると、潜在的に高速化することができます。
それでも利点がありますか?
まだ利点がありますか? アプリケーションが DBMS データへの共有メモリ アクセスを持っていない限り、優位性は常にストアド プロックにあります。
もちろん、ストアドプロシージャの最適化についての議論は、パラメータ化されたアドホックな SQL についての議論なしには完了しません。
パラメタライズド/プリペアード SQL
ストアドプロシージャとアドホック SQL の間のようなもので、クエリ値に "parameters" を使用するホスト言語での埋め込み SQL 文です。
SELECT .. FROM yourtable WHERE foo = ? AND bar = ?
これらは、現代のオプティマイザがクエリ実行計画をキャッシュ(再利用)するために使用できる、より一般化されたバージョンのクエリを提供し、結果としてストアドプロシージャのパフォーマンス上の利点の多くを得ることができるのです。
アドホック SQL DBMS のコンソール ウィンドウを開き、SQL 文を入力するだけです。過去には、DBMS がパラメータ化/保存された proc メソッドのようにクエリを事前に最適化する方法がなかったため、これらは (平均して) 最悪なパフォーマンスとなりました。
それでも不利ですか?
それでも不利ですか
必ずしもそうではありません。 必ずしもそうではありません。ほとんどの DBMS は、アドホックな SQL をパラメータ化されたバージョンに抽象化する機能を備えており、両者の違いを多かれ少なかれ否定しています。暗黙的にこれを行うものもあれば、コマンド設定で有効にしなければならないものもあります (SQL server: http://msdn.microsoft.com/en-us/library/ms175037.aspx Oracle。 http://www.praetoriate.com/oracle_tips_cursor_sharing.htm ).
教訓は? ムーアの法則は進み続け、DBMSのオプティマイザは、リリースされるたびに、より洗練されたものになっています。しかし、オプティマイザーで作業しているプログラマーは非常に頭が良く、パフォーマンスを向上させる方法を常に探していることを理解しておいてください。最終的には(まだそうなっていないとしても)アドホックなSQLのパフォーマンスはストアドプロシージャーのパフォーマンスと(平均して!)区別がつかなくなるでしょうから、どのような種類の 大規模な ストアド プロシージャを使用することは、私には時期尚早の最適化のように聞こえます。
とにかく、エッジケースを避けて、ごく普通の SQL を使用すれば、アドホックとストアドプロシージャの違いは感じられないと思います。
関連
-
[解決済み] SQLのカラム名があいまいな場合のクエリエラー
-
[解決済み] SQL Serverでシングルクォートをエスケープするにはどうすればよいですか?
-
[解決済み] Oracleの全テーブルのリストを取得しますか?
-
[解決済み] SQL Serverでストアドプロシージャ内のテキストを検索する
-
[解決済み] MySQLでFULL OUTER JOINを行うにはどうすればよいですか?
-
[解決済み] カラム名の変更 SQL Server 2008
-
[解決済み] フラットテーブルをツリーにパースする最も効率的/エレガントな方法は何ですか?
-
[解決済み] 文字列の一部をUPDATEおよびREPLACEする。
-
[解決済み] 項目xにアクセスできるように文字列を分割するにはどうすればよいですか?
-
[解決済み] Postgres でサブクエリを使用してテーブルの行を更新する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
windows mysql prompt access denied for user ''@'localhost' to database.
-
[解決済み] MongoDBに "like "を使ってクエリを実行する方法
-
[解決済み] SQL Serverでシングルクォートをエスケープするにはどうすればよいですか?
-
[解決済み] INNER JOIN ON vs WHERE句
-
[解決済み] PostgreSQLからのPL/pgSQL出力をCSVファイルに保存する
-
[解決済み] postgres: ユーザーをスーパーユーザーにアップグレードしますか?
-
[解決済み] SQL Server の CASE ステートメントで OR がサポートされていない。
-
[解決済み] 文字列の一部をUPDATEおよびREPLACEする。
-
[解決済み] DISTINCTでCOUNT(*)を選択する
-
[解決済み] "ON UPDATE CASCADE "を使用する場合について