4

Laurion Burchall がこれを読んでくれることを願っています :-)

100 万個の小さなレコードをできるだけ早く挿入する必要があります。

今、私は非常にタイトなループに陥っており、すべてのレコードについて、

a) start a transaction  (JetBeginTransaction)
b) prepare an update (JetPrepareUpdate)
c) add the row (JetSetColumns)
d) commit the transaction (JetCommitTransaction)

現在、このプロセスの間、私は 1 つのプロセッサでタイトなループに陥っています。ターゲット マシンには、複数の CPU、優れたディスク、および大量の空き RAM があります。

どうすればより良いパフォーマンスが得られるかを考えています。

トランザクションに関する限り、私はいくつかの実験を行い、1 つのトランザクションに多くのデータを入れすぎるとエラーが返されるという問題がありました。そこで何が起こっているのかをよりよく理解したいのですが、バグがありますか、それともトランザクションのサイズに上限がありますか? 上限がある場合、上限を拡大できますか? 私はこれを調査しているだけなので、トランザクションによって ESE が RAM でより多くのキャッシュを実行できるようになり、ディスク フラッシュが最小限に抑えられるのではないでしょうか? -これは単なる推測ですか?

一般に、複数のプロセッサ/大量の RAM/Nice ディスクを使用するにはどうすればよいですか? データベースを 2 回開いてそこから移動する必要がありますか? スレッドの安全性とトランザクションに関して何が起こるかはよくわかりません。DB に 2 つのハンドルがあり、それぞれがトランザクション内にある場合、1 つのハンドルへの書き込みは、コミットの直前に 2 番目のハンドルで使用できるようになりますか、それとも最初にコミットする必要がありますか?

どんなヒントでも大歓迎です

    here are the constraints    

a) I've got a million records that need to be written into the DB as fast as possible
b) to fully generate the record for insertion there are two searches that need to occur within the same table (seeking keys)
c) This is a rebuild/regeneration of the DB - it either worked, or it didnt.  
   If it didnt there is no going back, a fresh rebuild/regeneration is
   needed.  I cannot restart mid process and without all the data none of 
   the data is valuable.  READ: having one big transaction is fine if it 
   improves perf.  I'd like ESE to cache, in ram, if that helps perf.

ありがとう!

4

2 に答える 2

5

シングルスレッドのパフォーマンスに関して最も重要なことは、トランザクション モデルです。

1 つのトランザクションにさらに多くのデータを入れようとして失敗した場合は、おそらく JET_errOutOfVersionStore を受け取りました。Esent は、(ロールバックを有効にするために) トランザクションで実行されるすべての操作の元に戻す情報を追跡する必要があり、その情報はバージョン ストアに格納されます。バージョン ストアの既定のサイズは非常に小さいです。JET_paramMaxVerPages システム パラメータを使用して増やすことができます。1024 の値 (64MB のバージョン ストア) では、非常に大きなトランザクションが可能になります。トランザクションごとに 100 ~ 1000 回の挿入を行うことをお勧めします。

JetCommitTransaction を呼び出すと、Esent はログをディスクにフラッシュし、同期 I/O を生成します。これを避けるには、JET_bitCommitLazyFlush を JetCommitTransaction に渡します。トランザクションは引き続きアトミックですが、クラッシュの場合には永続的ではありません (正常に終了すれば問題ありません)。あなたの使用のためにそれが見つかるはずです。

昇順でレコードを挿入する場合は、シングル スレッド アプリケーションで問題を解決できる可能性があります。シーケンシャル挿入を行うように実装を変更できる場合は、そうする必要があります-それらははるかに高速です。ランダムな挿入の場合、複数のスレッドが役立ちます。複数のスレッドを使用するには、新しいセッション (JetBeginSession) を作成し、データベースを開く (JetOpenDatabase) 必要があります。Esent はスナップショット分離 ( http://en.wikipedia.org/wiki/Snapshot_isolation ) を使用するため、コミットされていない、またはトランザクションの開始後にコミットされていない他のセッションによって行われた変更を見ることはできません。これは、別のセッションがコミットされると変更を確認できる read-committed とは異なります。これに対処するには、作業をどのように分割するかを考える必要があるかもしれません。

于 2010-12-14T15:29:32.720 に答える
1

「順番に」挿入していることを確認してください。クラスター化された (主) キーとは何ですか? 人工オートインクですか?もしそうなら、あなたは順番に挿入しています。副次索引はいくつありますか? 理想的には、クラスター化された挿入のみなど、すべての挿入がインデックス順になるように、何も持たないことです。インデックス順に挿入すると、JetUpdate は単にインデックスの最後に追加されます。これは、インデックスの途中に挿入するよりもはるかに高速です。これがお役に立てば幸いです、イアン。

于 2013-02-25T14:48:21.350 に答える