【问题标题】:How to speed up Raven DB query performance?如何加快 Raven DB 查询性能?
【发布时间】:2021-03-01 15:08:10
【问题描述】:

谁能帮我加快查询速度?我正在使用 RavenDB 3.5.8,以下查询需要相当长的时间(首次加载时尤其如此):

var query = session
                .Query<Card>()
                .Include(p => p.AuthorId)
                .Include(p => p.CompanyId)
                .Where(x => !x.Id.StartsWith("Archived"))
                .Where(x => !x.IsDeleted);

do
{
    var popStash = stashedResults != null && stashedResults.Count > 0;
    if (popStash)
    {
        stashSkip = stashedResults.Count;
    }

    results = query
        .Statistics(out stats)
        .OrderByDescending(x => x.ModifiedAt)
        .Skip(this.ServerPage * this.ServerPageSize)
        .Take(this.ServerPageSize)
        .Select(MapCard)
        .Where(x => x.IsAuthorized)
        .Skip(clientPage * command.PageSize)
        .Take(command.PageSize - stashSkip)
        .ToList();

    if (popStash)
    {
        results = results.Union(stashedResults).ToList();
        stashedResults.Clear();
    }

    if (results.Count < command.PageSize)
    {
        ++this.ServerPage;
        clientPage = 0;

        if (results.Count > 0)
        {
            stashedResults = results;
        }
    }
    

} while (results.Count < command.PageSize &&
    stats.TotalResults >= (this.ServerPage * this.ServerPageSize) + this.ServerPageSize);

我知道这远非完美,但请注意,SkipTake 是必要的,因为 RavenDB 默认不支持身份验证,所以我必须 Map 每张卡并添加IsAuthorized 字段使用以下代码 sn-p:

IsAuthorized = session.Advanced.IsOperationAllowedOnDocument("Authorization/Users/" + user.Id, "Cards/View", card.Id).IsAllowed;

基本上发生的情况是,首先查询加载一堆卡片(实际上 ServerPageSize 定义了那里的卡片数量)而不考虑安全性,然后在应用安全性时加载 command.PageSize 卡片。 (网页动态加载卡片 - 前 50 张卡片被加载,在查看之后,另外 50 张卡片被抓取,依此类推..

谁能给我一些提示如何提高我的代码的性能?

【问题讨论】:

    标签: c# ravendb


    【解决方案1】:

    您应该能够使用 streaming 支持以避免多次查询。

    你也是在查询否定的,最好先查询肯定的然后否定。

    请注意,这意味着您正在运行一个非常昂贵的 SELECT N+1,对于每个结果,您都会得到一个查询。

    您为什么不使用授权捆绑查询过滤功能?

    在此处查看文档:

    https://ravendb.net/docs/article-page/3.5/Csharp/server/bundles/authorization#operations

    你错过了SecureFor的电话

    你可以使用:

    session.SecureFor("Authorization/Users/" + user.Id, "Cards/View");
    

    现在 RavenDB 将做过滤服务器端。

    【讨论】:

    • 是的,但我不能同时使用授权包和分页。 RavenDB 鼓励您使用分页。这就是为什么有统计机制,它返回总计数。到目前为止还可以。但是,当您想获取统计信息(总数)时,它将跳过授权。请参阅以下链接: - groups.google.com/g/ravendb/c/YrEulS6xwP8 - stackoverflow.com/questions/15357057/…
    • 为什么项目总数未知,查询将起作用并过滤不相关的数据。
    • 是的,过滤,但不考虑授权。这是我的主要问题。
    • 恐怕你不能两者都做。一般来说,您可以避免在授权查询中显示项目总数。
    • 我怕做不到。根据我的经验,我认为我也不能对 ravenDB 说我想要接下来的 50 个文档,我有权查看这些文档。因此,只能在加载文档后应用授权(session.SecureFor 在这种情况下似乎不起作用)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    相关资源
    最近更新 更多