0

在我的程序中,我从我的 MySQL 数据库中复制数据,理论上我正在通过分页减少结果集。对于 30 行数据,大约 25 列数据,每个单元格中没有太大的数据,似乎仍然需要很长时间 600-800 毫秒。

这只是我通过访问数据库来检索数据所必须承受的性能损失吗?我经常更新这些数据,每个用户都有不同的数据集,所以我无法将其缓存或预加载到内存中。

我会喜欢一些关于我如何从这里开始的建议。我看着制作一个单独的存储过程来为我的分页计算总行数,但主要的打击似乎是当我必须将数据复制到程序到一个列表中,然后为我的网页视图生成 JSON。

我对此有点陌生,我认为由于产生这些结果所花费的时间,我的前端页面的响应能力开始受到影响。1.8 - 2.5 秒的页面刷新时间似乎太长了,无法重新加载显示 30 个结果的网格。

先感谢您。

编辑:附加细节:

表中的所有主键都已编入索引。是的,我已经分析了耗时最长的 EF 查询,它似乎没有做任何比分页选择更多的事情。前任

sql = "System.Collections.Generic.List`1[PeerTrader.usercollectionenhancedview].OrderBy(Param_0 => Param_0.CardName).Skip(90).Take(30)"

我们可以将客户端排除在外,因为我正在我的控制器上测量诊断,基本上客户端不会为显示的呈现增加任何实际开销。基本上准备 JSon 数据以将其返回给客户端所需的时间是相同的。

它通常是 30 页(尽管当我将其减少到行数为 5 时它所花费的时间并没有真正改变)来自存储过程,结果总计数约为 20K。

真正的打击是在我实际从数据库中“读取”数据的地方。因此,无论我在哪里注入从数据库中实际加载结果的部分,似乎都是最大的打击。运行应该模拟我的服务器在 MySQL 服务器上进行的页面调用的分页查询会返回大约 60 毫秒的结果。

这是我的控制器操作:在下面的示例中,我将整个数据集复制到过滤器后的列表中,因为我在 5、30 或 20K 行中复制似乎无关紧要,它似乎是读取操作中的相同命中,然后它让我稍后在控制器中多次枚举数据集。

public ActionResult GridData(string sidx, string sord, int page, int rows, bool _search, string filters)
    {
    ///**********Diagnostics Start********
    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
    sw.Start();
    ///**********Diagnostics End********

    MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
    int currentUserID = (int)currentUser.ProviderUserKey;

    var serializer = new JavaScriptSerializer();
    //Filters f = (!_search || string.IsNullOrEmpty(filters)) ? null : serializer.Deserialize<Filters>(filters);
    Filters_IQueryable f = (!_search || string.IsNullOrEmpty(filters)) ? null : serializer.Deserialize<Filters_IQueryable>(filters);

    IQueryable<usercollectionenhancedview> query = db.SingleUserCollectionView(currentUserID).AsQueryable();


    var filteredQuery = (f == null ? query : f.FilterObjectSet(query)).ToList();

    ///**********Diagnostics Start********
    sw.Stop(); long t1 = sw.ElapsedMilliseconds; sw.Start();
    System.Diagnostics.Debug.WriteLine("");
    System.Diagnostics.Debug.WriteLine("**************");
    System.Diagnostics.Debug.WriteLine("T1: " + t1);
    ///**********Diagnostics End********

    int totalRecords;

    totalRecords = filteredQuery.Where(x => x.fk_IdUsers == currentUserID).Count();
    pagedQuery = filteredQuery.AsQueryable().Where(x => x.fk_IdUsers == currentUserID).OrderBy(sidx + " " + sord).Skip((page - 1) * rows).Take(rows);

     ///**********Diagnostics Start********
     sw.Stop(); long t2 = sw.ElapsedMilliseconds; sw.Start();
     System.Diagnostics.Debug.WriteLine("T2: " + t2);
     ///**********Diagnostics End********

我希望我已经添加了足够的额外信息以供进一步评论,如果不只是让我知道的话。我非常感谢您对我的问题的探索。

编辑2:

sql = "System.Data.Objects.ObjectResult1[PeerTrader.usercollectionenhancedview].OrderBy(Param_0 => Param_0.CardName).Skip(0).Take(30)" When I go looking on my DB, the actual call on the DB to do theorder by` 实际上需要相当长的时间,实际数据库本身需要 300 毫秒,所以看起来就像我追踪了一次昂贵的降级

4

1 回答 1

0
var filteredQuery = (f == null ? query : f.FilterObjectSet(query)).ToList();

上面的线看起来很可疑。见这里

ToList(IEnumerable) 方法强制立即查询评估

如果您只需要计数和 30 个项目,则无需实现 1000 多个结果。应重写以下查询以对数据库而不是物化集合进行操作。使用 count() 和 Skip().Take() 时生成的 SQL 应该足以将结果限制为您需要的结果,但您可能希望使用检查实际查询ObjectQuery.ToTraceString()

totalRecords = filteredQuery.Where(x => x.fk_IdUsers == currentUserID).Count();
pagedQuery = filteredQuery.AsQueryable().Where(x => x.fk_IdUsers == currentUserID)
                          .OrderBy(sidx + " " + sord).Skip((page - 1) * rows).Take(rows);

如果您仍然遇到问题并且这是只读情况,您可以尝试使用.AsNoTracking()并关闭任何代理生成。

于 2013-02-02T21:19:13.907 回答