我目前正在优化我们的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>();
答案 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;这种方式使您必须逐步浏览页面(我认为最流行的行为)
如果有人点击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 ;