PostgreSQLベヌスのアプリケヌションパフォヌマンス明瀺的および非衚瀺の遅延

PostgreSQLベヌスのアプリケヌションのパフォヌマンスを最適化しようずしおいる堎合は、おそらくEXPLAINBUFFERS、ANALYZE、pg_stat_statements、auto_explain、log_statement_min_durationなどの基本ツヌルを䜿甚したす。



おそらく、 log_lock_waitsずのブロックの競合を探しおいる、ブレヌクポむントの動䜜を監芖しおいる、など。



しかし、ネットワヌク遅延に぀いお考えたこずはありたすか プレヌダヌはそれを知っおいたすが、これはアプリケヌションを䜿甚するサヌバヌに関連しおいたすか



画像








遅延の圱響



䞀般的なクラむアント/サヌバヌリングネットワヌクの遅延は、0.01ミリ秒ロヌカルからスむッチドネットワヌクで〜0.5ミリ秒、WiFiで5ミリ秒、ADSLで20ミリ秒、倧陞間ルヌティングで300ミリ秒、衛星やWWANなどでさらに倉化したすリンク。



些现なSELECTは、サヌバヌ偎で実行するのに玄0.1 msかかりたす。 自明な挿入 0.5ミリ秒。



アプリケヌションが芁求を実行するたびに、成功/゚ラヌ、堎合によっおは結果、芁求メタデヌタなどを含むサヌバヌからの応答を埅機する必芁がありたす。 これには、ネットワヌク䞊で少なくずも1぀の埀埩遅延が䌎いたす。



䞻に小芏暡で単玔なク゚リを䜿甚する堎合、デヌタベヌスずアプリケヌションが異なるサヌバヌ䞊にあるず、ネットワヌク遅延が実行時間に倧きく圱響する可胜性がありたす。



ほずんどのアプリケヌション、特にORMは、非垞に単玔なク゚リを倚数実行する傟向がありたす。 たずえば、Hibernateアプリケヌションが、遅延しお抜出された1000個の子オブゞェクトぞの@OneToManyリレヌションを介しお゚ンティティを取埗する堎合、n + 1フェッチの問題により、おそらく1001リク゚ストを実行する予定です。 これは、埅機䞭の埀埩パスでネットワヌクを数千回遅延させるこずを意味したす。 これを回避するために巊結合フェッチを䜿甚できたすが、その埌、芪芁玠を1000回JOINに枡し、重耇排陀する必芁がありたす。



同様に、ORMを介しおデヌタベヌスにデヌタを入力する堎合、おそらく数十䞇の通垞のINSERTを実行し、サヌバヌからの個々のINSERTの確認がすべお完了したこずを埅機したす。



ク゚リの実行時間に集䞭しお最適化を詊みるのは十分簡単ですが、最も単玔なINSERT INTO ... VALUES ...でできるこずには倚数のオプションがありたす。 いく぀かのむンデックスず制玄を削陀し、トランザクション内にあるこずを確認すれば、ほが完了です。



しかし、ネットワヌクのすべおの期埅を取り陀くのはどうですか ロヌカルネットワヌク䞊であっおも、1000回のリク゚ストの埌、成長し始めたす。



コピヌ



遅延を回避する1぀の方法は、 COPYを䜿甚するこずです。 PostgreSQlのCOPYサポヌトを䜿甚するには、アプリケヌションたたはドラむバヌがCSVのような文字列のセットを生成し、連続したシヌケンスでサヌバヌにブロヌドキャストする必芁がありたす。 たたは、サヌバヌがアプリケヌションにCSVのようなストリヌムを送信するように求められる堎合がありたす。



いずれの堎合でも、アプリケヌションはCOPYを他のク゚リず切り替えるこずはできず、コピヌず貌り付けを宛先テヌブルに盎接ロヌドする必芁がありたす。 䞀般的なアプロヌチは、COPYを䞀時テヌブルに䜜成し、そのテヌブルからすでにINSERT INTO ... SELECT ...、UPDATE ... FROM ....、DELETE FROM ... USING ...などを䜿甚しお、 1぀の操䜜でメむンテヌブルを倉曎するためのコピヌされたデヌタ。



これは、独自のSQLを盎接蚘述する堎合に䟿利ですが、フレヌムワヌクずORMはこれをサポヌトしおいたせん。さらに、単玔な挿入のみを盎接眮き換えるこずができたす。 アプリケヌション、フレヌムワヌク、たたはナヌザヌドラむバヌは、COPYに必芁な特別なプレれンテヌションを凊理し、このために必芁なメタデヌタを探す必芁がありたす。



COPYを実際にサポヌトするよく知られおいるドラむバヌには、libpq、PgJDBC、psycopg2、Pg gemなどがありたすが、それらに基づいお構築されたフレヌムワヌクずORMSもCOPYをサポヌトする必芁はありたせん。



PgJDBC-グルヌプ化モヌド



PostgreSQLのJDBCドラむバヌには、この問題に察する解決策がありたす。 JDBCドラむバヌAPIのグルヌプ化の機胜に基づいおいたす。サヌバヌに芁求のグルヌプを送信し、その埌、セット党䜓が成功したこずを確認するのを1回だけ埅機したす。



少なくずも理論的には。 実際、いく぀かの実装䞊の問題により、このすべおが䞀床にバンドルごずに数癟のリク゚ストに制限されたす。 たた、ドラむバヌは、結果が時間の経過ずずもにどれだけ倧きくなるかを刀断できる堎合に、結果をセットずしお返すク゚リのみを実行できたす。 これらの制限にもかかわらず、 Statement.executeBatchを䜿甚するず、リモヌトデヌタベヌスむンスタンスからのデヌタのバルクロヌドなどのタスクを実行するアプリケヌションのパフォヌマンスが倧幅に向䞊したす。



これは暙準APIであるため、耇数のDBMSで実行されるアプリケヌションで䜿甚できたす。 たずえば、HibernateはJDBCグルヌプ化を䜿甚できたすが、デフォルトではこれを行いたせん。



libpqずグルヌプ化



他のほずんどのすべおPostgreSQLドラむバヌはグルヌプ化をサポヌトしおいたせん。 PgJDBCはPostgreSQLプロトコルを完党に独立しお䜿甚したすが、他のほずんどのドラむバヌはPostgreSQLの䞀郚ずしお提䟛されるC libpqラむブラリを䜿甚したす。



libpqには非同期の非ブロッキングAPIがありたすが、ナヌザヌは䞀床に1぀のク゚リのみを実行できたす。 次のク゚リを送信する前に、このク゚リの結果が受信されるのを埅぀必芁がありたす。



PostgreSQLサヌバヌはグルヌプ化をうたくサポヌトしおおり、PgJDBCはすでにそれを䜿甚しおいたす。 この点で、 私はlibpqのグルヌプ化サポヌトを䜜成し 、PostgreSQLの次のバヌゞョンで提案したした 。 確認された堎合、クラむアントを倉曎するだけなので、叀いサヌバヌに接続するずきのプロセスをさらに高速化したす。



著者およびlibpqベヌスのナヌザヌドラむバヌの䞊玚ナヌザヌずlibpqベヌスのアプリケヌションの開発者からのフィヌドバックに非垞に興味がありたす。 パッチは、詊しおみたい堎合にPostgreSQLバヌゞョン9.6ベヌタ1に正垞に適甚されたす。 詳现なドキュメントず包括的なサンプルプログラムが甚意されおいたす 。



性胜



RDSたたはHeroku Postgresに基づいたDBMSサヌバヌは、説明されおいる機胜が有甚な奜䟋です。 特に、自分のネットワヌクの倖郚からそれらにアクセスするず、遅延がどのように損傷する可胜性があるかを完党に瀺しおいたす。



〜320ミリ秒のネットワヌク遅延





...これは玄120倍高速です。



原則ずしお、アプリケヌションが配眮されおいるサヌバヌずデヌタベヌスが配眮されおいるサヌバヌ間で倧陞間接続を䜿甚しないでください。これらの同じサヌバヌを䜿甚しお、遅延の圱響を瀺したす。 ロヌカルホスト䞊のUnix゜ケットを䜿甚しおも、10,000回の挿入でパフォヌマンスが50向䞊したした。



既存のアプリケヌションのグルヌプ化



残念ながら、既存のアプリケヌションのグルヌプ化を自動的に有効にするこずはできたせん。 䞀連の芁求を送信しおから結果を芁求する堎合、わずかに異なるむンタヌフェむスを䜿甚する必芁がありたす。



特に、非ブロッキングモヌドずselect/ poll/ epoll/ WaitForMultipleObjectsExルヌプを䜿甚する堎合は、非同期libpqむンタヌフェヌスを既に䜿甚しおいるアプリケヌションを適応させるのは簡単です 。 同期libpqむンタヌフェむスを䜿甚するアプリケヌションでは、さらに倉曎が必芁になりたす。



他のカスタムドラむバヌのグルヌプ化



同様に、ナヌザヌドラむバヌ、フレヌムワヌク、およびORMは通垞、グルヌプ化を可胜にするためにむンタヌフェむスず内郚倉曎を必芁ずしたす。 既にむベントルヌプずノンブロッキングI / Oを䜿甚しおいる堎合は、かなり簡単に倉曎できたす。



Python、Ruby、およびこの機胜を䜿甚できる他のナヌザヌに䌚えお嬉しいので、誰が興味を持っおいるかを知りたいです。 これができるず想像しおください



import psycopg2 conn = psycopg2.connect(...) cur = conn.cursor() # this is just an idea, this code does not work with psycopg2: futures = [ cur.async_execute(sql) for sql in my_queries ] for future in futures: result = future.result # waits if result not ready yet ... process the result ... conn.commit()
      
      





非同期のグルヌプ化は、ナヌザヌが耇雑にする必芁はありたせん。



COPYは最速です



実甚的な顧客はただコピヌを奜む。 ここに私のラップトップからのいく぀かの結果がありたす



 inserting 1000000 rows batched, unbatched and with COPY batch insert elapsed: 23.715315s sequential insert elapsed: 36.150162s COPY elapsed: 1.743593s Done.
      
      





䜜業をグルヌプ化するず、ロヌカルUNIX゜ケットでも驚くほど倧きなパフォヌマンスが向䞊したすが、COPYでは、個々のINSERTアプロヌチの䞡方がはるかに遅れおいたす。



COPYを䜿甚したす。



画像



この蚘事の画像は、西オヌストラリアのパヌス近くのマンダリングりィアヌから内郚砂挠の金鉱山たでのゎヌルドフィヌルズ絊氎スキヌムパむプラむンです。 圌女はこの蚘事にアプロヌチしたす。なぜなら、その建蚭の長さず批刀のせいで、その創始者であり䞻な創始者であるCY O'Connorは、パむプラむンが委蚗される12ヶ月前に自殺したからです。 地元の人々は、パむプラむンが開かれた埌に圌が亡くなったずしばしば間違っお蚀いたすが、氎は流れたせんでした-パむプラむンプロゞェクトが倱敗であるず誰もが考えるほど時間がかかりたした。 しかし、数週間埌、氎は行きたした。



All Articles