RavenDB随机缓慢故障排除

时间:2013-01-25 17:10:26

标签: c# wpf ravendb

我有一个使用RavenDB的WPF应用程序。在其中一个窗口,我可以反复点击“刷新”按钮来更新网格。每次刷新都会导致RavenDB查询。奇怪的是,每隔一段时间查询都需要很长时间。例如,我可以连续七次点击“刷新”按钮,网格将在不到一秒的时间内刷新。然后,在第8次尝试时,将需要12秒。然后,我可以再次点击刷新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);
    }

1 个答案:

答案 0 :(得分:2)

在这个例子中你有很多自定义代码,所以很难确切地知道发生了什么。但我很确定问题围绕着这一行:

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

在生产查询中,这不是您想要的。它主要用于单元测试。

尝试完全删除该行,或者如果确实需要等待,请改为指定一个截止点,例如:

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

如果可能,请考虑升级到RavenDB 2.0。它具有更好的性能和功能。