在针对不同数据访问方法的ASP.NET Web应用程序上运行性能测试时,我注意到Entity Framework / LINQ在我的本地系统上运行 <20>比其他方法快20倍+返回任何结果数据行/对象。当查询执行导致空数据集时,我本地系统上的查询执行时间对于所有数据访问方法几乎相同。
当在托管的ASP.NET和MS SQL环境中执行相同的测试时,如果返回非空数据集,则EF / LINQ性能没有任何显着差异。当返回一个空数据集时,EF / LINQ比我的测试中的其他数据访问方法运行速度慢~10。
以下是我测试过的所有数据访问方法的列表:
在使用ADO,ODS,EF / SP的测试中使用相同的存储过程。 测试查询的参数正在改变。
以下是测试的统计信息,以秒为单位的时间,查询主要生产表中有数百万条记录的MS SQL数据库,大约300条返回。
本地系统:
虚拟服务器上的ASP.NET和MS SQL主机:
以下是查询参数定义空结果集时的测试统计结果:
本地系统:
虚拟服务器上的ASP.NET和MS SQL主机:
问题:
你有没有观察过这种现象?
你对这种现象有什么解释吗?
看起来ASP.NET Web应用程序(?)+ EF在同一系统上运行时会直接访问MS SQL内存吗?
[源代码第二天添加12-SEP-2015 10:25 GMT + 3]
string msg = ...
string empNum = ...
GUID? cId = ...
DateTime? startDate = ...
DateTime? endDate = ...
TimeSpan e5 = default(TimeSpan);
int c5 = -1; // record counter
int c51 = -1; // unique record IDs counter
Stopwatch sw2 = Stopwatch.StartNew();
step = "(5)";
using (var fx = new fxPaySlipsEntities())
{
var accruedAmounts = from cl in fx.Clients
where cl.Id == cId
join c in fx.Companies on cl.Id equals c.ClientId
join d in fx.Departments on c.Id equals d.CompanyId
join e in fx.Employees on cl.Id equals e.ClientId
where d.Number == e.CurrentDepartment
join p in fx.PaySlips on d.Id equals p.DepartmentId
where e.Id == p.EmployeeId
join s in fx.sumNs on p.Id equals s.SlipId
join code_ in fx.codes on cl.Id equals code_.ClientId
where s.t1 == code_.t1
select new
{
PaySlipId = p.Id,
PaySumSource = "N",
PayGroup = (s.t0 == 10 || s.t0 == 61) ? 3 : 1,
TabNumLowered = e.NumberLowered,
s.t0,
code_.t1,
PayCode = code_.localt1,
payCodeStr = code_.Name,
sumId = s.Id,
sAmount = s.sAmount,
PayDate = p.mDate,
MonthNum = p.mDate.Month,
YearNuim = p.mDate.Year,
MyClientId = cl.Id
};
var retainedAmounts = from cl in fx.Clients
where cl.Id == cId
join c in fx.Companies on cl.Id equals c.ClientId
join d in fx.Departments on c.Id equals d.CompanyId
join e in fx.Employees on cl.Id equals e.ClientId
where d.Number == e.CurrentDepartment
join p in fx.PaySlips on d.Id equals p.DepartmentId
where e.Id == p.EmployeeId
join s in fx.sumDs on p.Id equals s.SlipId
join code_ in fx.codes on cl.Id equals code_.ClientId
where s.t1 == code_.t1
select new
{
PaySlipId = p.Id,
PaySumSource = "D",
PayGroup = (s.t0 == 10 || s.t0 == 61) ? 3 : 2,
TabNumLowered = e.NumberLowered,
s.t0,
code_.t1,
PayCode = code_.localt1,
payCodeStr = code_.Name,
sumId = s.Id,
sAmount = -s.sAmount,
PayDate = p.mDate,
MonthNum = p.mDate.Month,
YearNuim = p.mDate.Year,
MyClientId = cl.Id
};
var allAmounts = accruedAmounts.Concat(retainedAmounts);
var allAmountsFiltered = allAmounts.Where(x =>
(cId == null || x.MyClientId == cId) &&
(tabNum == null || empNum.Equals(x.TabNumLowered, StringComparison.InvariantCultureIgnoreCase)) &&
(
(startDate == null && endDate == null) ||
(startDate != null && endDate == null && x.PayDate >= startDate) ||
(startDate == null && endDate != null && x.PayDate <= endDate) ||
(x.PayDate >= startDate && x.PayDate <= endDate)
));
c5 = 0;
decimal sum = 0;
dx = new Dictionary<int, int>();
foreach (var item in allAmountsFiltered)
{
// if you know how to do this summing up and unique Ids counting
// in a concise LINQ expression please comment
if (!dx.ContainsKey(item.PaySlipId)) dx.Add(item.PaySlipId, item.PaySlipId);
sum += item.sAmount;
c5++;
}
c51 = dx.Count;
e5 = sw2.Elapsed;
// It could it be that the actual EF/LINQ query execution
// starts after elapsed time is retrieved above?
// But as I have noted the "speedy EF/LINQ query execution phenomenon"
// doesn't appear on hosted ASP.NET and MS SQL environment where
// IIS and MS SQL are very probably running on different physical servers
// or at least in the different virtual servers boxes...
msg = string.Format("EF/LINQ: test: Retrieved {0} acc./ret. sums records for {1} paylists, Emp# = {2}, time period from {3:dd/MM/yyyy} till {4:dd/MM/yyyy}, sum = {5:#0.00}",
c5, c51, empNum, startDate, endDate, sum);
}
...