使用EF 6和SQL 2014。
假设您有一个索引正确且标准化的数据库。将实体拉入内存然后在IEnumerables上执行联接还是让EF通过IQueryable联接是“更好”的做法?
更好->更快的执行时间,更少的数据库读取,内存使用。
内存示例:
using (var context = myDbContext())
{
var table1 = await context.Table1.ToListAsync();
var table2 = await context.Table2.ToListAsync();
var table3 = await context.Table3.ToListAsync();
var resultSet = table1
.Join(table2, t1 => t1.Id, t2 => t2.Table1Id, (t1,t2) => new {t1, t2})
.Join(table3, x => x.t2.Table2Id, t3 => t3.Table2Id, (x, t3) => new { x.t1, x.t2, t3})
.ToList();
}
示例EF:
using (var context = myDbContext())
{
var resultSet = await context.Table1
.Join(context.Table2, t1 => t1.Id, t2 => t2.Table1Id, (t1,t2) => new {t1, t2})
.Join(context.Table3, x => x.t2.Table2Id, t3 => t3.Table2Id, (x, t3) => new { x.t1, x.t2, t3})
.ToListAsync();
}
答案 0 :(得分:3)
您怎么知道一辆汽车是否比另一辆汽车快?驱赶他们并比较时间。
通常,数据库在连接数据方面比内存中的Linq更有效(由于预先计算的索引,哈希等),但是肯定会出现内存中的情况更快的情况。但是,当您不将所有数据都拉到内存中时,通过网络上的更少数据带来的好处可能会比连接中的任何性能改进带来更大的改变。
因此,没有确切的答案。从起作用开始,然后通过测量更改前后的时间来专注于性能改进。
答案 1 :(得分:0)
执行数据库查询的较慢部分之一是将数据从DBMS传输到本地进程。因此,明智的做法是限制要传输到您的流程的数据量。仅传输您实际打算使用的数据。
因此,如果您查询“教师与学生”,您将知道老师的ID将等于外键“ TeacherId in every
学生”。那么,如果您已经知道值的话,为什么要为老师的1000名学生中的每位学生运输此外键?
让DBMS执行查询的另一个原因是因为对数据库中的软件进行了优化以执行查询。如果DBMS为查询创建了一个临时表,并且检测到新查询需要相同的临时表,那么即使查询来自其他进程,智能DBMS也会重用该临时表。
智能DBMS将检测到某些索引比其他索引使用得更多,并将它们保留在内存中,而不是一直从磁盘读取它们。
因此,DBMS具有各种技巧来加快查询的执行速度。
您可以通过以下方法来查看此技巧的帮助:连续执行两次查询,并查看第二个查询的执行速度比第一个查询快。这也是您无法衡量让给定查询由DBMS执行还是在本地内存中执行它更快的原因。,如某些建议所示。
唯一正确的方法是,在较长的时间段内(几分钟,如果不是几小时),使用大量执行这些查询的流程来评估各种查询所选择的策略。您肯定会知道的一件事是,执行AsEnumerable查询不能从其他人执行的查询中受益。