1

ポーカー ハンドの履歴を解析し、そのデータを postgres データベースに保存しています。以下にその概要を示します。 ここに画像の説明を入力

パフォーマンスが比較的悪く、ファイルの解析には数時間かかります。データベース部分が全プログラム時間の 97% を占めていることがわかります。そのため、少し最適化するだけで、これが大幅に高速化されます。

私が今設定している方法は次のとおりです。

  1. 次のファイルを文字列に読み込みます。
  2. 1 つのゲームを解析し、オブジェクト GameData に格納します。
  3. すべてのプレイヤーについて、std::map に彼の名前があるかどうかを確認します。もしそうなら; playerid を配列に保存して 5 に進みます。
  4. プレーヤーを挿入し、それを std::map に追加し、プレーヤー ID を配列に格納します。
  5. playerids 配列を使用して、このベッティング ラウンドの動きを挿入し、moveid を配列に格納します。
  6. moveids 配列を使用して、movesequence を挿入し、movesequenceids を配列に格納します。
  7. これが最後のラウンドでない場合は、5 に進みます。
  8. movesequenceids 配列を使用して、ゲームを挿入します。
  9. これが最終ゲームでない場合は、2 に進みます。
  10. これが最後のファイルでない場合は、1 に進みます。

すべての動き、すべての動きのシーケンス、すべてのゲームに対してクエリを送信しているため、明らかにクエリが多すぎます。最高のパフォーマンスを得るには、それらをどのようにバンドルすればよいですか? 少しコードを書き直しても構わないので、遠慮しないでください。:)

前もって感謝します。

CX

4

1 に答える 1

1

クエリ、スキーマ、または Pg バージョンがなければ、これに答えるのは非常に困難です。

ただし、一般に、これらの問題に対する解決策は、多くの作業を繰り返さないように、作業をより大きな粗いバッチにバッチ処理することです。最も重要なのは、すべてを 1 つのトランザクションで実行することです。

あなたはトランザクションについて何も言っていないので、これらすべてを自動コミット モードで行っているのではないかと思います。計画が悪い。BEGINプロセス全体を andでラップしてみてくださいCOMMIT。数分ごと、数十ゲームごとなど、非常に長時間実行されるプロセスの場合はCOMMIT、プログラムがその時点からインポートを再開するために使用できるチェックポイント ファイルまたは DB エントリを作成し、新しいトランザクションを開いて続行します。

複数の行を同じテーブルに挿入する場合は、複数値の挿入を使用すると役立ちます。例えば:

INSERT INTO some_table(col1, col2, col3) VALUES
('a','b','c'),
('1','2','3'),
('bork','spam','eggs');

synchronous_commit=offと aを使用してコミット率を向上させることができますがcommit_delay、作業をより大きなトランザクションにバッチ処理している場合はあまり役に立ちません。

非常に良いオプションの 1 つは、新しいデータをUNLOGGEDテーブル(PostgreSQL 9.1 以降) またはTEMPORARYテーブル (すべてのバージョンですが、セッションが切断されると失われる) に挿入し、プロセスの最後にすべての新しい行をメイン テーブルにコピーしてドロップすることです。次のようなコマンドを使用してテーブルをインポートします。

INSERT INTO the_table
SELECT * FROM the_table_import;

そんな時にCREATE TABLE ... LIKE便利です。

もう 1 つのオプション (実際には上記のより極端なバージョン) は、結果を読み取って変換するときに結果を CSV フラット ファイルに書き込んCOPYでから、データベースに書き込むことです。あなたは C++ で作業しているので、 を使用していると思いますlibpq- その場合はlibpqtypes. は一括読み込み用の apilibpqへのアクセスを提供するCOPYpsqlため、アプリで生成された CSV データを読み込むために を呼び出す必要はありません。

于 2012-08-25T02:23:44.417 に答える