0

Postgresql 9.1 NPGSQL 2.0.12

postgresqlデータベースに保存したいバイナリデータがあります。ほとんどのファイルは正常にロードされますが、大きなバイナリ(664 Mb)ファイルが問題を引き起こしています。Npgsqlを介したラージオブジェクトサポートを使用してファイルをpostgresqlにロードしようとすると、postgresqlサーバーは「メモリ不足」エラーを返します。

私は現在、4Gb RAMを搭載したワークステーションでこれを実行しており、postgresqlがアイドル状態で実行されている状態で2Gbが解放されています。

これは私が使用しているコードであり、PGFoundryNpgsqlユーザーズマニュアルを基にしています。

using (var transaction = connection.BeginTransaction())
{
    try
    {
        var manager = new NpgsqlTypes.LargeObjectManager(connection);
        var noid = manager.Create(NpgsqlTypes.LargeObjectManager.READWRITE);
        var lo = manager.Open(noid, NpgsqlTypes.LargeObjectManager.READWRITE);
        lo.Write(BinaryData);
        lo.Close();
        transaction.Commit();
        return noid;
    }
    catch
    {
        transaction.Rollback();
        throw;
    }
}

postgresqlのメモリ設定をデフォルトからあらゆる種類の値に変更してみました:

  • shared_buffers
  • work_mem
  • Maintenance_work_mem

これまでのところ、postgresqlは優れたデータベースシステムであることがわかりましたが、これは現在のところショーストッパーであり、このサイズのファイルをデータベースに取り込むことができないようです。手動でファイルをチャンクに切り刻んで、クライアント側を再作成する必要はありません。

助けてください!?

4

2 に答える 2

2

答えは、LargeObjectクラスのWrite()メソッドをバイト配列のチャンクで繰り返し呼び出すことだと思います。データのチャンク化を処理する必要はないと言ったのは知っていますが、実際に意味したのは、データを個別のLargeObjectにチャンク化することでした。このソリューションは、配列をチャンク化することを意味しますが、それでも1つのオブジェクトとしてデータベースに保存されます。つまり、ファイルの一部を追跡する必要はなく、1つのOIDだけです。

 do 
 {
   var length = 1000;
   if (i + length > BinaryData.Length) length = BinaryData.Length - i;
   byte[] chunk = new byte[length];
   Array.Copy(BinaryData, i, chunk, 0, length);
   lo.Write(chunk, 0, length);
   i += length;
 } (i < BinaryData.Length)
于 2013-01-24T22:14:33.840 に答える
1

1回の700MB操作を実行する必要があるいくつかの接続用にメモリを予約するには、max_connectionsの数を減らしてみてください。work_mem(操作ごとに使用可能なメモリ)を1GBに増やします。700MBを1つのフィールドに詰め込もうとすると奇妙に聞こえます。

shared_buffersのサイズを4096MBに増やします。

于 2013-01-24T20:33:45.227 に答える