【问题标题】:How to improve ASP.NET MVC3 app data query performance?如何提高 ASP.NET MVC3 app 数据查询性能?
【发布时间】:2012-08-20 07:58:59
【问题描述】:

有一个基于 ASP.NET MVC3 的图书管理系统 web 应用程序。 点击图书索引页面时,数据查询很慢,需要等待几秒才能响应。 BookController中Action Index的代码如下:

    public ViewResult Index(string sortOrder, int? page)
    {
        ViewBag.NameSortParam = string.IsNullOrEmpty(sortOrder) ? "desc" : "";
        ViewBag.CurrentSort = sortOrder;

        BookModel books = from b in db.Books select b; // db = new BookContext();
        switch (sortOrder) {
            case "desc":
                books = books.OrderByDescending(b => b.Name);
                break;
            default:
                books = books.OrderBy(b => b.Name);
                break;
        }
        int pageSize = 15;
        int pageNumber = (page ?? 1);

        return View(books.ToPagedList(pageNumber, pageSize));
    }

在我看来,慢的主要原因是服务器在所有数据都准备好之前没有响应客户端。这个过程需要很长时间。

不知道如何解决这个问题,请问有什么方法可以提高这种情况下的数据查询性能吗?谢谢!

更新: 后端数据库是 SQL Server Compact Edition 4.0

更新 我在下面更新了我的逻辑代码,orderby 在skip 和take 语句之前使用。一切顺利。谢谢大家的帮助。

books = (from b in db.Books
                       orderby b.Name descending
                       select b)
                       .Skip((page - 1) * pageSize)
                       .Take(pageSize)
                       .ToList();

【问题讨论】:

  • 你的逻辑很简单,所以这里没有太多需要改进的地方。您可以对Book 实体进行缓存(请求/会话/应用程序),或者在Book 表的Name 列上添加数据库索引。索引还为 ORDER BY 查询提供种子。而且也很奇怪,需要很长时间,Books 表中有多少行?也许缓慢是由其他代码引起的。你做过分析吗?
  • 我猜 ToPagedList 正在从“书籍”表中获取所有数据。如果是这样,你不应该使用这个函数来获取你的页面数据。使用程序获取页面数据是最好的方法。对于表格,您可以为某些列设置索引。
  • 先检查ToPagedList是在数据库服务器还是内存中应用分页?
  • 你能分析一下 books.ToPagedList 生成的 SQl,看看那里发生了什么。
  • @nemesv nemesv,谢谢你的回答。我是数据查询和缓存技术的新手,你说的我很难实现。顺便说一句,数据库中没有存储大数据,最多一万。

标签: asp.net asp.net-mvc-3 entity-framework linq-to-sql


【解决方案1】:

在将数据集过滤为您需要的数据之前,您正在加载所有书籍(使用ToPagedList)。更改您的查询并使用Skip 和Take 方法而不是ToPagedList。

【讨论】:

  • 你好,zippyV,你能给我看一些代码sn-ps吗,我是新手。
  • return View( books.Skip( pageNumber * pageSize ).Take( pageSize ) );
  • 我 99% 确定扩展方法中的 ToPagedList 形成了 PagedList library,并且实现正确使用了 Skip and Take。
  • 是的,我也检查过:它使用 Skip and Take 和另一个查询来获取项目的总数。
  • 在skip和take之前,需要orderby操作。谢谢你的帮助。
【解决方案2】:

在 Books.Name 列上放置索引(包含列:包括列表中需要的那些),在 C# 端查询仅需要您的字段:

books.Select(x => new {
                       x.Name,
                       x.Author,
                       x.Description,
                       x.ID }).ToPagedList(/*....*/)./*...*/)

我会负责 ToPagedList 的实现。

【讨论】:

  • 如果不在where 子句中使用列上的索引,则它是无用的。
  • 这不是真的,因为如果表在排序列上没有索引(包括其他列),那么它将扫描整个表;如果有任何有用的东西,数据库引擎将扫描索引。这将以更少的 I/O 结束,并且索引排序类型可能与查询中的排序顺序相同,但如果不是,它将扫描索引反向顺序,这比在查询运行时重新排序数据要快得多。
  • 由于没有应用过滤器,所以无论如何都会扫描整个表,因此任何索引都是无用的。
  • 你对全表扫描是正确的,但如果他只选择那些真正需要的列(并且存在于一个有用的索引中),它会快得多。
  • @PeterKiss 嗨,我不知道如何为列添加索引,你能告诉我代码 sn-ps,谢谢。
【解决方案3】:

在方法上使用 OutputCaching,由两个参数变化。对此的概述是detailed here。

[OutputCache(Duration=60,VaryByParam="sortOrder;page;")]
public ViewResult Index(string sortOrder, int? page)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2010-09-06
    • 2013-08-03
    相关资源
    最近更新 更多