加载分页数据时的行数性能影响,任何想法?

时间:2017-09-22 06:28:12

标签: javascript c# sql-server asp.net-mvc entity-framework

我目前正在优化我们的Web应用程序,我不确定如何从这里开始:有一个大型SQL数据库,其中包含一个包含数百万个条目的大型存档表。这些行需要尽可能快地在我们的可视化中显示(通过一个或两个字段和时间戳过滤,并通过Ajax传递到客户端的JS部分)。我在数据库中创建了有用的索引,我也通过归档实体中的导航属性消除了交叉引用的需要,这样我就可以从一个表中读取数据并在前端完成剩下的工作,从而大大提高了性能

在分析不同的瓶颈时,我发现了一个问题:我没有在前端请求所有匹配数据(没有人一次看10000行)但是使用了跳过的分页机制( )并在服务器端take()。这也可以很好地和快速地工作,但是为了获得匹配行的总量,我必须在某处进行计数。而且这个count()非常昂贵:来自前端的完整请求周期通常需要大约10到30毫秒,但是当我向查询添加一个计数时,这大约会达到450毫秒。

现在我想知道如何继续:我应该忽略延迟而只是忍受它吗?或者在不知道元素总数的情况下有一个很好的分页方法吗?我的意思是,不知何故,前端需要知道行数,因为它需要计算页数并启用/禁用“下一页”按钮等。

有解决此问题的好方法吗?

更新:这是我的代码,有一些评论:

var query = from x in db.ValueArchive select x;

// Filter by DatapointIds, if there are any
if (request.DatapointIds.Count>0)
{
    query = query.Where(x => request.DatapointIds.Contains((int)x.DataPointId));
}

// Filter by StationIds, if there are any
if (request.StationIds.Count > 0)
{
    query = query.Where(x => request.StationIds.Contains((int)x.StationId));
}

// Get number of matching rows after filtering
// This is the bottleneck!
response.numFound = query.Count();

// Paging
query = query.OrderBy(x => x.ID).Skip(request.Start == 0 ? 0 : request.Start-1).Take(request.Length);

// Add paging info to response
response.Start = request.Start;
response.Length = request.Length;

// Convert datetimes to ISO8601
response.Rows = query.Select(x => new { d = x.DataPointId, s = x.StationId, t = x.DateValue.Value, v = x.Value })
    .ToList()
    .Select(x => new { d = x.d, s = x.s, t = x.t.ToString("o"), v = x.v }).ToList<Object>();

3 个答案:

答案 0 :(得分:2)

要执行<u>_contained <b>**within**</b> this_</u>,SQL Server将使用最窄的非聚集索引来计算所有行。因此,如果表没有任何非聚集索引,则必须扫描整个表。 如果你有一个,那么你可以使用它(更多信息here):

SELECT COUNT(*)

作为一种解决方法,您可以使用Microsoft在右键单击表并选择属性时快速显示行数的技术。

SELECT OBJECT_NAME(s.id) [YourTable], s.rowcnt [Row_Count]
FROM sys.sysindexes s WITH (NOLOCK)
WHERE s.indid in (0,1)
ORDER BY s.rowcnt desc

您可以使用ADO执行此(或生成sql函数)代码并获取结果(而不是在您的实体上运行select sum (spart.rows) from sys.partitions spart where spart.object_id = object_id(’YourTable’) and spart.index_id < 2 方法)。

答案 1 :(得分:1)

  

或者有一种很好的方法可以在不知道总数的情况下进行分页   元素数量?

是的,有可能 您不必调用count()来获取要进行分页的项目总数。 项目COUNT不是强制性的。

在某个时间点,pageIndex = n,如果返回的项目的数量&lt; pageSize ==&gt; n是最后一页

  • 点击返回==&gt;获取pageIndex = n-1的项目。
  • 点击下一步==&gt;获取pageIndex = n + 1的项目。

=&GT;这种方式使您必须逐步浏览页面(我认为最流行的行为)

如果有人点击last =&gt;只有在这种情况下,您才能获得物品数量。让我们看看你如何使用Google搜索。你有没有浏览过最后一页?

答案 2 :(得分:0)

COUNT(*)OVER()将为您提供总计数,而不管在同一查询中是否进行分页,而无需额外查询:

select 
    row_number() OVER (order by  col1,col2 ) rowNumber,
    1 Page,
    (CEILING(CasT(COUNT(*) OVER () as float)/30)) Pages,
    COUNT(*) OVER () Rows, 

    col1,col2

from mytable mainlist 
where   myfilters=myfiltervalue
order by rowNumber 
OFFset (1-1)*30 rows 
FETCH NEXT 30 rows only ;