機能性能


46

ストアドプロシージャのパフォーマンス(以前の記事)使いやすさが疑わしいMySQLのバックグラウンドから来て、私はPostgreSQLを会社の新製品として評価しています。

私がやりたいことの1つは、アプリケーションロジックの一部をストアドプロシージャに移動することです。そのため、ここでは、特にパフォーマンスの落とし穴に関して、PostgreSQL(9.0)で関数を使用する際のDOおよびDO N'T(ベストプラクティス)を求めています。


パフォーマンスに関係のないものについては答えに言及したくないということですか?
ジャックダグラス

Chris Traversは、ストアドプロシージャを使用する利点について多くのブログを作成しています。たとえば、ledgersmbdev.blogspot.de / 2012/07 / およびここ:ledgersmbdev.blogspot.de/2012/07/…ブログをざっとてください。このトピックに関する多くの興味深い記事。
a_horse_with_no_name

回答:


51

厳密に言えば、「ストアドプロシージャ」という用語は、Postgres 11で導入されたPostgresのSQLプロシージャを指しています

関数もありますが、ほとんど同じですが、まったく同じではありません。それらは最初からありました。

関数とは、LANGUAGE sql基本的には(常に内部で実行し、そのため、原子、関数ラッパーでプレーンなSQLコマンドでちょうどバッチファイルである単一のパラメーターを受け入れトランザクション)。SQL関数内のすべてのステートメントは、一度に計画さます。これは、ステートメントを次々に実行する場合とは微妙に異なり、ロックが取得される順序に影響する場合があります。

それ以外の場合、最も成熟した言語はPL / pgSQLLANGUAGE plpgsql)です。これはうまく機能し、過去10年間にリリースごとに改善されてきましたが、SQLコマンドの接着剤として最適です。(SQLコマンドを使用する場合を除き)大量の計算を対象とするものではありません。

PL / pgSQL関数は、準備済みステートメントのようなクエリを実行します。キャッシュされたクエリプランを再利用すると、いくつかの計画オーバーヘッドが削減され、同等のSQLステートメントよりも少し高速になります。これは、状況によっては顕著な影響があります。また、次の関連質問のような副作用がある場合があります。

これには、マニュアルで説明されているように、準備されたステートメントの長所と短所があります。不規則なデータ分布と変化するパラメータを持つテーブルでクエリの動的SQLとのEXECUTE所与のパラメータ(単数または複数)のための最適化された実行計画からの利得は、再計画のコストを上回る場合に良好に機能することができます。

Postgres 9.2の一般的な実行プランはセッションのためにキャッシュされますが、マニュアルを引用しているため

これは、パラメータのない準備されたステートメントに対して直ちに発生します。そうでない場合は、5回以上の実行により、一般的な計画コストの見積りよりも見積もられた平均コスト(計画オーバーヘッドを含む)のプランが作成された後にのみ発生します。

ほとんどの場合、(ab)useを使用せずに(オーバーヘッドを追加せずに)両方の世界のベストを取得しEXECUTEます。PostgreSQL WikiのPostgreSQL 9.2の新機能の詳細。

Postgres 12では、一般的なプランまたはカスタムプランを強制する追加のサーバー変数がplan_cache_mode導入されています。特別な場合には、注意して使用してください。

アプリケーションからデータベースサーバーへの追加のラウンドトリップ防止するサーバー側の機能を使用すると、大きな利益を得ることができます。サーバーをできるだけ一度に実行し、明確に定義された結果のみを返します。

複雑な関数、特にテーブル関数(RETURNING SETOF recordまたはTABLE (...))のネスト避けてください。関数は、クエリプランナーの最適化の障壁となるブラックボックスです。外部クエリのコンテキストではなく、個別に最適化されているため、計画が簡単になりますが、完全な計画とは言えません。また、関数のコストと結果サイズを確実に予測することはできません。

この規則の例外は単純なSQL関数(LANGUAGE sql)で、これは「インライン化」できます-いくつかの前提条件が満たされている場合Neil Conwayによるこのプレゼンテーション(高度なもの)で、クエリプランナーの機能について詳しく読んでください。

PostgreSQLでは、関数は常に単一のトランザクション内で自動的に実行さます。すべて成功するか、何もありません。例外が発生すると、すべてがロールバックされます。しかし、エラー処理があります ...

それが、関数が正確に「ストアドプロシージャ」でない理由でもあります(その用語は時々誤解を招くように使用されますが)。一部のコマンドは好き、またはそれらが機能で許可されていないので、トランザクションブロック内で実行することはできません。(SQLプロシージャにも、Postgres 11の時点ではまだありません。これは後で追加される可能性があります。)VACUUMCREATE INDEX CONCURRENTLYCREATE DATABASE

私は長年にわたって何千ものplpgsql関数を書いてきました。


2
@nhahtdh:「自動トランザクション」は専門用語ではありません。それは、エレガントな言い方ではありませんでした..明確化した後、今言っていることです。自律的なトランザクションではありません。「自律」は、たまたま同様の単語です。
アーウィンブランドステッター

4
こことSOからコンパイルされた回答は、壮大なPostGreSQLベストプラクティスハンドブックになる可能性があります。
ダボス

10

いくつかのこと:

  • PGはステートメントをインライン化できるため、可能な場合はSQLを関数言語として使用します
  • IMMUTABLE / STABLE / VOLATILEを正しく使用します。PGが不変または安定している場合に結果をキャッシュできるためです。
  • 関数を実行する代わりに入力がnullの場合、PGは単にnullを返すことができるため、STRICTを正しく使用します。
  • 関数言語としてSQLを使用できない場合は、PL / V8を検討してください。私が実行したいくつかの非科学的なテストでは、PL / pgSQLよりも高速です
  • トランザクション外で発生する可能性がある長時間実行されるプロセスには、LISTEN / NOTIFYを使用します
  • キーベースのページネーションはLIMITベースのページネーションよりも速くなる可能性があるため、関数を使用してページネーションを実装することを検討してください
  • 機能の単体テストを確認してください

PL / V8がPL / pgSQLよりも速いという主張を目にするのは初めてです。それをサポートする(公開されている)数字はありますか?
a_horse_with_no_name

@a_horse_with_no_nameいいえ、私はしません。私が言ったように、私はいくつかの非科学的なテストをしました。それらはほとんどデータアクセスではなくロジックでした。私はクリスマスにいくつかの再現可能なテストをして、ここに再投稿しようとします。
ニールマクギガン

@a_horse_with_no_nameは、FizzBu​​zz plv8とplpgsqlの簡単な例です:blog.databasepatterns.com/2014/08/plv8-vs-plpgsql.html
ニール

8

一般的に、アプリケーションロジックをデータベースに移動すると、高速になります-結局、データの近くで実行されます。

SQL言語関数は、コンテキスト切り替えを必要としないため、他の言語を使用する関数よりも高速であると確信しています(100%確信はありません)。欠点は、手続き論理が許可されないことです。

PL / pgSQLは組み込み言語の中で最も完成度が高く、機能も完備していますが、パフォーマンスのためにCを使用できます(ただし、計算量の多い機能にのみ有効です)


7

postgresqlのユーザー定義関数(UDF)を使用すると、非常に興味深いことができます。たとえば、使用できる言語は数十種類あります。組み込みのpl / sqlおよびpl / pgsqlは、機能も信頼性も高く、サンドボックスメソッドを使用して、ユーザーが非常に危険なことをしないようにします。Cで記述されたUDFは、データベース自体と同じコンテキストで実行されるため、究極のパワーとパフォーマンスを提供します。ただし、小さな間違いでもバックエンドがクラッシュしたりデータが破損したりするなど、大きな問題を引き起こす可能性があるため、それは火で遊ぶようなものです。pl / R、pl / ruby​​、pl / perlなどのカスタムpl言語を使用すると、データベースとアプリの両方のレイヤーを同じ言語で書くことができます。これは、perlプログラマーのjavaやpl / pgsqlなどにUDFを書くために教える必要がないことを意味するため、便利です。

最後に、pl / proxy言語があります。このUDF言語を使用すると、スケーリングを目的として、数十以上のバックエンドpostgresqlサーバーでアプリケーションを実行できます。これはSkypeの良き人々によって開発されたもので、基本的に貧しい人の水平スケーリングソリューションを可能にします。驚くほど簡単に書くこともできます。

さて、パフォーマンスの問題について。これは灰色の領域です。1人用のアプリを書いていますか?それとも1,000ですか?または10,000,000のために?アプリを構築してUDFを使用する方法は、スケーリングの方法に大きく依存します。何千人ものユーザーのために書いている場合、あなたがしたい主なことは、可能な限りデータベースの負荷を減らすことです。データベースに移動されてデータベースに戻されるデータの量を減らすUDFは、IO負荷を減らすのに役立ちます。ただし、CPU負荷が増加し始める場合は、問題になる可能性があります。一般的に、IO負荷の削減が最優先事項であり、CPUが過負荷にならないようにUDFが効率的であることを確認することが次です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.