0

RavenDB を使用する WPF アプリケーションがあります。ウィンドウの 1 つで、[更新] ボタンを繰り返し押してグリッドを更新できます。更新ごとに RavenDB クエリが発生します。奇妙なのは、クエリに時間がかかる場合があることです。たとえば、更新ボタンを 7 回続けて押すと、グリッドは 1 秒以内に更新されます。その後、8 回目の試行では 12 秒かかります。その後、Refresh をさらに 11 回押すと、再びすばやく実行されますが、12 回目には、再び 12 秒かかります。このようにかなり一貫しています。遅延があるたびに常に12秒かかるようです。それは何ですか?

クエリは次のとおりです。

IQueryable<EntityBase> installationSummaries =
    QueryAndSetEtags(session => session.Query<InstallationSummary>()
    .Include(x => x.ApplicationServerId)
    .Include(x => x.ApplicationWithOverrideVariableGroup.ApplicationId)
    .Include(x => x.ApplicationWithOverrideVariableGroup.CustomVariableGroupId)
    .Customize(x => x.WaitForNonStaleResults())
    .OrderByDescending(summary => summary.InstallationStartUtc)
    .Take(numberToRetrieve)
    );

    HydrateInstallationSummaries(installationSummaries);

    return installationSummaries.AsEnumerable().Cast<InstallationSummary>();

遅延は常にこのコード行にあります (entityBases は上記のクエリからの戻り値です)。

List<EntityBase> entityBaseList = entityBases.ToList();

RavenDB でこのような問題をトラブルシューティングする正しい方法は何ですか? 次に何を試せばよいかわかりません。

注: このコードは長い間変更されていません。現在、RavenDB 960 を使用しています。これは RavenDB 573 では発生しませんでした。

編集 - このクエリの周りで他に何が起こっているかを示す追加のコード。

    private static void HydrateInstallationSummaries(IQueryable<EntityBase> installationSummaries)
    {
        // Note: We use session.Load() below so that we get the information from the session, and not another trip to the DB.
        foreach (InstallationSummary summary in installationSummaries)
        {
            HydrateInstallationSummary(summary);
        }
    }

    private static void HydrateInstallationSummary(InstallationSummary summary)
    {
        if (summary == null) { return; }

        summary.ApplicationServer =
            QuerySingleResultAndSetEtag(session => session.Load<ApplicationServer>(summary.ApplicationServerId))
            as ApplicationServer;

        summary.ApplicationWithOverrideVariableGroup.Application =
            QuerySingleResultAndSetEtag(session => session.Load<Application>(summary.ApplicationWithOverrideVariableGroup.ApplicationId))
            as Application;

        if (summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId == null) { return; }

        summary.ApplicationWithOverrideVariableGroup.CustomVariableGroup =
            QuerySingleResultAndSetEtag(session =>
            {
                if (session.Advanced.IsLoaded(summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId))
                {
                    return session.Load<CustomVariableGroup>(summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId);
                }
                return null;  // Note: We can be missing a custom variable in the session because someone deleted it.
                ;
            })
            as CustomVariableGroup;
    }

そして、ここに QueryAndSetEtags() があります:

    protected static IQueryable<EntityBase> QueryAndSetEtags(Func<IDocumentSession, IQueryable<EntityBase>> func)
    {
        if (func == null) { throw new ArgumentNullException("func"); }

        IQueryable<EntityBase> entities = func.Invoke(_session);
        SetEtags(entities, _session);
        return entities;
    }

    protected static void SetEtags(IEnumerable<EntityBase> entityBases, IDocumentSession session)
    {
        foreach (EntityBase entityBase in entityBases)
        {
            SetEtag(entityBase, session);
        }
    }

    protected static void SetEtag(EntityBase entityBase, IDocumentSession session)
    {
        entityBase.Etag = (Guid)session.Advanced.GetEtagFor(entityBase);
    }
4

1 に答える 1

2

この例には多くのカスタム コードが含まれているため、何が起こっているのかを正確に把握するのは困難です。しかし、問題は次の行を中心に展開していると確信しています。

.Customize(x => x.WaitForNonStaleResults())

これは、本番クエリでは必要ありません。単体テストの主な目的です。

その行を完全に削除してみるか、本当に待つ必要がある場合は、代わりに次のようなカットオフ ポイントを指定します。

.Customize(x => x.WaitForNonStaleResultsAsOfNow())

可能であれば、RavenDB 2.0 へのアップグレードを検討してください。はるかに優れたパフォーマンスと機能を備えています。

于 2013-01-25T18:21:57.280 に答える