4

私は RavenDB の使用方法を学ぼうとしており、そのために基本的な例を作成しました。ストアの初期化とクエリには膨大な時間がかかるようです!

static void Main( string[] args )
{
    const bool createNewEntities = true;

    var sw = new Stopwatch();
    using( var store = new EmbeddableDocumentStore {DataDirectory = "~\\Data"} )
    {
        sw.Start();
        store.Initialize();
        sw.Stop();
        Console.WriteLine( "Initialized in {0} ms.", sw.ElapsedMilliseconds );

        if (createNewEntities)
        {
            sw.Reset();
            sw.Start();
            using( var session = store.OpenSession() )
            {
                sw.Stop();
                Console.WriteLine();
                Console.WriteLine( "Opened session in {0} ms.", sw.ElapsedMilliseconds );

                for( var i = 0; i < 10; i++ )
                {
                    var entity = new EntityA( "Entity A " + DateTime.Now.ToLongTimeString() );

                    sw.Reset();
                    sw.Start();
                    session.Store( entity );
                    sw.Stop();

                    if (i < 3)
                        Console.WriteLine( "Stored '{0}' in {1} ms.", entity.Name, sw.ElapsedMilliseconds );
                }

                sw.Reset();
                sw.Start();
                session.SaveChanges();
                sw.Stop();
                Console.WriteLine( "Saved changes in {0} ms.", sw.ElapsedMilliseconds );
            }
        }


        sw.Reset();
        sw.Start();
        using( var session = store.OpenSession() )
        {
            sw.Stop();
            Console.WriteLine();
            Console.WriteLine( "Opened EntityA session in {0} ms.", sw.ElapsedMilliseconds );

            sw.Reset();
            sw.Start();
            var entities = session.Query<EntityA>().ToArray();
            sw.Stop();
            Console.WriteLine("Queried for all {0} EntityA in {1} ms.", entities.Length, sw.ElapsedMilliseconds);
        }


        sw.Reset();
        sw.Start();
        using( var session = store.OpenSession() )
        {
            sw.Stop();
            Console.WriteLine();
            Console.WriteLine( "Opened EntityA session (again) in {0} ms.", sw.ElapsedMilliseconds );

            sw.Reset();
            sw.Start();
            var entities2 = session.Query<EntityA>().ToArray();
            sw.Stop();
            Console.WriteLine( "Queried (again) for all {0} EntityA in {1} ms.", entities2.Length, sw.ElapsedMilliseconds );
        }
    }


    Console.WriteLine();
    Console.WriteLine();
    Console.WriteLine( "Press ENTER to exit..." );
    Console.ReadLine();
}

これにより、次の出力が生成されます。

6132 ms で初期化されます。

3 ミリ秒でセッションを開始しました。
「エンティティ A 08:50:14」を 129 ミリ秒で保存。
「エンティティ A 08:50:15」を 0 ミリ秒で保存しました。
「エンティティ A 08:50:15」を 0 ミリ秒で保存しました。
29 ミリ秒で変更を保存しました。

0 ミリ秒で EntityA セッションを開きました。
463 ミリ秒で 10 個の EntityA すべてを照会しました。

0 ミリ秒で EntityA セッションを (再び) 開きました。
1 ミリ秒で 10 個の EntityA すべてを (再度) 照会しました。

この大まかな例から、次のことがわかります。

  • ストアの初期化には膨大な時間がかかります!!
  • 最初のエンティティ (10 個のうち) を格納するには、かなりの時間がかかります。
  • すべてのエンティティのクエリには、最初は時間がかかりますが、2 回目はまったく時間がかかりません。

特定のタイプ (EntityA) のすべてのドキュメントについて DB に適切にクエリを実行するにはどうすればよいですか? 確かに、RavenDB がすべてのクエリにインデックスを必要とするわけではありませんか? 特に基準のないクエリではありませんか?

(注: デスクトップ アプリケーションに埋め込まれた DB を使用するつもりです。この場合、すべてのドキュメントを一覧表示して DB の内容を表示します。)

4

1 に答える 1

5

遅延の理由は次の 3 つです。

初期化の遅延
ドキュメント ストアの初期化は、最もコストのかかる操作の 1 つです。RavenDB の組み込みモードを実行しているため、データベースへの接続を設定するだけでなく、実際にデータベースの実行も開始する必要があります。私のマシン (2.3Ghz i5 ラップトップ) では、初期化に 2516ms かかりました。

完全な RavenDB サーバー (組み込みではない) を実行している場合、遅延の大部分はサーバー自体の起動時に発生します。クライアントの初期化は大幅に高速になります。

これは、IDocumentStore(埋め込みか通常かを問わず) シングルトンとして保持することを意図していることを考えると、妥当な動作です。このインスタンスは、アプリケーション内に 1 つだけ存在する必要があり、起動時に作成され、シャットダウン時に破棄される必要があります。

First Store Delay
独自の を提供していないためId、Raven はHiLo 生成アルゴリズムを使用して自動生成しています。これには、データベースから割り当て可能な ID のブロックを割り当てることが含まれますが、これには少し時間がかかります。ブロックが使い果たされるまでデータベースにヒットする必要がないため、後続の呼び出しは高速になります。

独自のプロパティを提供し、 、 などIdの有効な識別子を入力すると、キーの生成がスキップされるため、はるかに高速になります。entities/1entities/2

クエリの遅延静的インデックスを指定しない場合
の最初の呼び出しでこれは、メタデータ .Query<T>()を使用してエンティティ タイプでフィルタリングする必要があるため、「すべて」のエンティティを取得する場合にも当てはまりますRavenDB のコレクションは仮想的なものであり、メタデータによって決定されます。ドキュメントは実際にはすべて一緒に存在するため、メタデータによるクエリとフィルタリング以外に、「コレクション」内のすべてのアイテムを取得する方法はありません。Raven-Entity-Name

表示されている遅延の一部は、構築中の動的インデックスです。その後、アイテムのインデックス作成に遅延が発生します。さらにアイテムを追加した場合 (たとえば、数百)、ほぼ同じ遅延が発生しますが、すべてのアイテムが返されるわけではないことに注意してください。インデックスは作成されたばかりなので古くなり、Raven は少数のインデックスのみを返します。あなたのようなテストでは、古くない結果を明示的に待ちたいと思うでしょう。実際のアプリケーションでは、代わりに静的インデックスを事前に定義することをお勧めします。実際、静的インデックスを使用することで、クエリを高速化できます。遅延は、クエリの時間ではなく、インデックスの作成時に移動されます。

インデックスの使用をまったく避けたい場合は、別の方法があります。

session.Advanced.LoadStartingWith<EntityA>("EntityAs/");

このメソッドは、フィルター処理にメタデータを使用しません。キー名自体を使用します。クエリを使用せずにドキュメント ストアに直接アクセスするため、はるかに高速です。多くの結果を得るにはページ分割する必要がありますが、とにかくクエリについても同じ懸念があります。しかし、この方法では、デフォルトのページ サイズがはるかに小さい (25) ため、遅かれ早かれ間違いなくそれに遭遇します。

これがあなたの懸念に答えたことを願っています。他にもありましたらコメントで教えてください。

于 2013-02-10T02:04:29.537 に答える