我的数据库包含数十亿行。
我创建了从用户参数中接收参数并通过这些参数切割数据库的函数。
这适用于小型数据库(30000 行),但是当我尝试在大型数据库上使用此函数时,我从 SQLSERVER 得到了 TIMEOUTEXCEPTION
。
这是我的代码:
public static IQueryable<LogViewer.EF.InternetEF.Log> ExecuteInternetGetLogsQuery(FilterCriteria p_Criteria, ref GridView p_Datagrid)
{
IQueryable<LogViewer.EF.InternetEF.Log> internetQuery = null;
using (InternetDBConnectionString context = new InternetDBConnectionString())
{
internetQuery = context.Logs;
if ((p_Criteria.DateTo != null && p_Criteria.DateFrom != null))
{
internetQuery = internetQuery.Where(c => c.Timestamp >= p_Criteria.DateFrom && c.Timestamp < p_Criteria.DateTo);
}
else if (p_Criteria.DateFrom != null && p_Criteria.DateFrom > DateTime.MinValue)
{
internetQuery = internetQuery.Where(c => c.Timestamp >= p_Criteria.DateFrom);
}
else if (p_Criteria.DateTo != null && p_Criteria.DateTo > DateTime.MinValue)
{
internetQuery = internetQuery.Where(c => c.Timestamp < p_Criteria.DateTo);
}
if (!string.IsNullOrEmpty(p_Criteria.FreeText))
{
internetQuery = internetQuery.Where(c => c.FormattedMessage.Contains(p_Criteria.FreeText));
}
if (p_Criteria.Titles.Count > 0)
{
internetQuery = internetQuery.AsEnumerable().Where(c => p_Criteria.Titles.Contains(c.Title)).AsQueryable();
}
if (p_Criteria.MachineNames.Count > 0)
{
internetQuery = internetQuery.AsEnumerable().Where(c => p_Criteria.MachineNames.Contains(c.MachineName)).AsQueryable();
}
if (p_Criteria.Severities.Count > 0)
{
internetQuery = internetQuery.AsEnumerable().Where(c => p_Criteria.Severities.Contains(c.Severity)).AsQueryable();
}
internetQuery= internetQuery.OrderByDescending(c=>c.LogID);
if (internetQuery.Count() > p_Criteria.TopValue)
{
internetQuery = internetQuery.Take(p_Criteria.TopValue);
}
p_Datagrid.DataSource = internetQuery;
p_Datagrid.DataBind();
return internetQuery;
}
}
我的 SQL 版本是 2005。
我在 p_Datagrid.DataBind();
行上遇到异常。
有什么建议吗? 谢谢
最佳答案
我可以看到您有以下选项:
- 增加超时时间(Bad idé 只是将问题转移到 future )
- 而不是执行 linq 查询。通过存储过程获取数据
- 制作网格页面。因此,您只需检索目标页面的数据。
- 查看查询计划,看看您是否可以在您正在执行
where
语句和order by
的列上建立任何索引。 - 为什么您需要在数据网格中包含数十亿行。有什么要求?也许您可以只显示
top 1000
或top 10000
。因为从用户的角度来看,我看不出有十亿行的网格有任何好处。
那只是我的想法。
编辑
如果我有这个功能,我会开始查看这部分代码:
if (p_Criteria.Titles.Count > 0)
{
internetQuery = internetQuery.AsEnumerable().Where(c => p_Criteria.Titles.Contains(c.Title)).AsQueryable();
}
if (p_Criteria.MachineNames.Count > 0)
{
internetQuery = internetQuery.AsEnumerable().Where(c => p_Criteria.MachineNames.Contains(c.MachineName)).AsQueryable();
}
if (p_Criteria.Severities.Count > 0)
{
internetQuery = internetQuery.AsEnumerable().Where(c => p_Criteria.Severities.Contains(c.Severity)).AsQueryable();
}
这实际上使结果成为一个 IEnumerable,然后您在内存中执行 where
语句并调用数据库。执行此操作也可能会遇到问题,因为当您调用相关表时,它会调用数据库。也许您可以获取行,然后使用 IQueryable
的 id 执行 contains
。执行此操作时使用 IQueryable
尿布的所有优点。
关于c# - 从大型数据库中检索行时优化灵活的 Linq to Entity 标准的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10190881/