Pythonを使用したPostgresからの毎秒100万行

画像



asyncpgは、PostgreSQLを操作するための新しいPythonオープンソースライブラリです。 それはasyncioとPython 3.5を使用して書かれました。 asyncpgは、Python、NodeJS、Goの同様の実装の中でPostgreSQLを操作するための最速のドライバーです。



なぜasyncpgなのですか?



PostgreSQLをバックエンドとして、次世代データベースであるEdgeDBを作成しています。 PostgreSQL自体の高性能、低遅延、および追加機能が必要です。



最も明白なオプションは、PostgreSQLを操作するための最も一般的なPythonドライバーであるpsycopg2を使用することです。 彼は優れたコミュニティを持ち、安定しており、実績があります。 psycopg2の上に、非同期インターフェイスを実装するaiopgもあります。 それから明らかな質問は-なぜあなたの自転車を書くのですか? 簡単な答え:PostgreSQLのパフォーマンスと機能のサポート。 以下では、これについてさらに詳しく検討します。



特徴



データ型のサポート



psycopg2に対する主な不満は、次のようなさまざまなタイプのデータの平凡な処理でした。 配列と複合型。 多くの異なるデータ型は、PostgreSQLの際立った機能の1つです。 さらに、初期状態では、psycopg2は単純なデータ型(整数、文字列、時刻、日付)のみをサポートしています。 それは、あなたが他の何かのためにあなたのタイプを書くようにします。



この主な理由は、psycopg2がデータベースサーバーとテキスト形式で通信するという事実にあります。そのため、特に複合データ型の場合、多くのデータを解析する必要があります。



psycopg2とは異なり、asyncpgはPostgreSQLバイナリI / Oプロトコルを使用します。これは、パフォーマンスの利点に加えて、コンテナーデータ型(配列、範囲、複合型)のネイティブサポートも備えています。



準備されたリクエスト



Asyncpgは、準備されたPostgreSQLステートメントも使用します。 これは、クエリプランの解析、分析、構築の繰り返しを回避するため、最適化の絶好の機会です。 さらに、asyncpgは、準備された各ステートメントのI / Oデータをキャッシュします。



asyncpgの準備済みステートメントは、直接作成して使用できます。 クエリ結果を受信および分析するためのAPIを提供します。 ほとんどの要求メソッドは接続を直接作成し、asyncpgは準備された要求を作成してキャッシュします。



導入が簡単



asyncpgのもう1つの重要な機能は、依存関係がないことです。 PostgreSQLプロトコルの直接実装は、libpqをインストールする必要がないことを意味します。 pip install asyncpg



実行pip install asyncpg



です。 さらに、LinuxおよびmacOSでの手動アセンブリ用のパッケージを提供しています(Windowsは将来的に計画されています)。



性能



PostgreSQLプロトコルを直接実装することで、速度を大幅に向上できることがすぐに明らかになりました。 uvloopの過去の経験から、Cythonを使用すると効率的で生産的なライブラリを作成できることがわかりました。 asyncpgは、メモリ管理と高度な最適化を備えたCythonで完全に記述されています。 その結果、asyncpgはpsycopg2(またはaiopg)よりも平均で3倍高速でした。



テスト中



uvloop同様にpgbenchをテストし、asyncpgおよびその他のPostgreSQLドライバーの実装をレポートするための個別のユーティリティを作成しました。 リクエストの速度(1秒あたりの行数)と遅延を測定しました。 これらのテストの主な目的は、このドライバーのオーバーヘッドを見つけることです。



正直に言うと、すべてのテストは同じスレッド(Golangの場合はGOMAXPROCS = 1)で非同期モードで実行されました。 Pythonドライバーは、uvloopを使用して起動されました。



このテストは、次の構成のクリーンサーバーで行われました。





使用されたドライバー:





画像

画像

グラフは、4種類のクエリを実行して得られた結果の平均値を示しています。



-pg_typeテーブルからすべての行(約350行)を選択する直接クエリ。 これは、アプリケーション要求の総数にかなり近いです。 このテストでは、asyncpgは1秒あたり100万行のタイトルパフォーマンスを示しています。 詳細。



-要求は、単一の整数で構成される1000行を生成します。 このテストは、レコードを作成して結果を取得するときのパフォーマンスを表示するように設計されています。 詳細。



-要求は100行を返します。各行には1 KBのバイナリデータ(blob)が含まれています。 これはストレスの多いI / Oテストです。 詳細。



-クエリは100行を返します。各行には100個の整数の配列が含まれます。 このテストは、配列のデコード速度を確認するように設計されています。 ここで、asyncpgは高速なgolang実装よりも遅いことが判明しました。 これには、Pythonでタプルを作成および削除するコストが含まれます。 詳細。



おわりに



Pythonのおかげで、高性能でスケーラブルなシステムを作成できると確信しています。 これを行うには、高速で高品質のドライバー、イベントループ、およびフレームワークを作成する努力をする必要があります。



asyncpgは、この方向へのステップの1つです。 これは、意味のある設計の結果であり、uvloopの作成経験と、Cythonおよびasyncioの効率的な使用に支えられています。



PostgresからPythonへの記事翻訳1M行/秒



All Articles