c# – 构建linq查询以获得最快性能的正确方法?
这里也提出了类似的问题,但没有一个符合我的需要.
我做了测试用例,看看哪个更快.但我觉得我的 linq代码仍然很慢.如何构建 linq代码以获得更快的性能? 其他人说使用double .Tolist()会导致操作变慢,当我测试它时,它表明它比任何其他测试都快. 测试: Preparation --------------------------------------------------------------- return Properties of UserInfo(userinf,true){ UserID = userinf.UserID; FirstName = userinf.user.FirstName; MiddleName = userinf.user.MiddleName; LastName = userinf.user.LastName; LoginID = userinf.user.LoginID; Birthday = userinf.Birthday; } skip = 0; take = 100; total table records = 304; Linq to Entity Framework 提琴手:v2.4.0.0 https://127.0.0.1/..../RetrieveUserInfo?skip=0&take=100 { "client":{ "SessionID":"5433ab64-7e0d-444f-b886-a901ea9a0601" },"session":{ "SessionID":"35b75daa-25ad-45a4-9f99-0e69ec3b66a4" } } //Test 1 //1) 00:00:15.3068755 -- Attempt1 //2) 00:00:13.8207905 -- Attempt2 //3) 00:00:16.2489294 -- Attempt3 var list = (from usr in dbase.userinfoes select usr).OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); userlist = (from i in list select new UserInfo(i,true)).ToList(); ///Test 2 //1) 00:00:15.3908803 //2) 00:00:14.8818512 //3) 00:00:19.4761140 var list = (from usr in dbase.userinfoes.AsEnumerable().OrderBy(i => i.UserID).Skip(skip).Take(take).ToList() select new UserInfo(usr,true)).ToList(); //Test 3 //1) 00:00:30.1937270 //2) 00:00:24.1003784 //3) 00:00:28.8806519 var list = dbase.userinfoes.OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); userlist = (from i in list select new UserInfo(i,true)).ToList(); //Test 4 //1) 00:00:57.2652754 //2) 00:00:54.4051118 //3) 00:00:55.3251644 var list = (from usr in dbase.userinfoes select usr).ToList(); userlist = (from i in list select new UserInfo(i,true)).OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); //Test 5 //1) 00:01:06.8378229 //2) 00:01:01.2845053 //3) 00:00:55.0721499 var list = from usr in dbase.userinfoes select usr; userlist = (from i in list.AsEnumerable() select new UserInfo(i,true)).OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); // Test 6 // VERY LONG. It tooks all records first and construct UserInfo one by one before doing the skip and take var list = (from usr in dbase.userinfoes.AsEnumerable() select new UserInfo(usr,true)).OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); //Test 7 // VERY LONG. It tooks all records first and construct UserInfo one by one before doing the skip and take var list = from usr in dbase.userinfoes.AsEnumerable() select new UserInfo(usr); 适合快速搜索的代码.感谢casperOne指出,在服务器上执行的排序,跳过和取得更快. 这是最终的代码: var list = (from usr in dbase.userinfoes .OrderBy(i => i.UserID) .Skip(skip) .Take(take) .AsEnumerable() select new UserInfo(usr,true)).ToList(); 1) 00:00:10.9210513 2) 00:00:10.8270973 3) 00:00:10.8250151 感谢Richard Neil Ilagan的最终代码. 解决方法
这就是为什么每个人都表现得如此以及为什么你看到你所看到的:
测试1: ///Test 2 //1) 00:00:15.3068755 -- Attempt1 //2) 00:00:13.8207905 -- Attempt2 //3) 00:00:16.2489294 -- Attempt3 var list = (from usr in dbase.userinfoes select usr).OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); userlist = (from i in list select new UserInfo(i,true)).ToList(); 这绝对是最快的.它是最快的,因为订购,跳过和取消都在服务器上执行.因为你可能有索引,所以服务器很强大(功能强大)等等.它可以比你在客户端实现整个集合然后在那里执行操作更快地处理这些操作. UserInfo仅在后处理列表上构建. 测试2: ///Test 2 //1) 00:00:15.3908803 //2) 00:00:14.8818512 //3) 00:00:19.4761140 var list = ( from usr in dbase.userinfoes.AsEnumerable(). OrderBy(i => i.UserID).Skip(skip).Take(take).ToList() select new UserInfo(usr,true) ).ToList(); 这应该具有与测试7相同的性能影响;对 这有点像异常.我很想知道发送到服务器的SQL是什么(假设您正在使用SQL服务器或一些基于SQL的后端),以确保它正在选择所有记录. UserInfo仅在后处理列表上构建. 测试3: //Test 3 //1) 00:00:30.1937270 //2) 00:00:24.1003784 //3) 00:00:28.8806519 var list = dbase.userinfoes.OrderBy(i => i.UserID). Skip(skip).Take(take).ToList(); userlist = (from i in list select new UserInfo(i,true)).ToList(); 同样,order by,skip和take正在服务器上进行.你实现了两次列表(你有两次ToList调用),这是我可以看到的开销的唯一解释. UserInfo仅在后处理列表上构建. 测试4: //Test 4 //1) 00:00:57.2652754 //2) 00:00:54.4051118 //3) 00:00:55.3251644 var list = (from usr in dbase.userinfoes select usr).ToList(); userlist = (from i in list select new UserInfo(i,true)). OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); 你现在正在内存中实现整个列表,所以现在有更多的开销. UserInfo在预处理列表上构建. 测试5: //Test 5 //1) 00:01:06.8378229 //2) 00:01:01.2845053 //3) 00:00:55.0721499 var list = from usr in dbase.userinfoes select usr; userlist = (from i in list.AsEnumerable() select new UserInfo(i,true)). OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); 与测试二相同,您在客户端执行所有操作. UserInfo在预处理列表上构建. 测试6: // Test 6 // VERY LONG. It tooks all records first and construct // UserInfo one by one before doing the skip and take var list = (from usr in dbase.userinfoes.AsEnumerable() select new UserInfo(usr,true)). OrderBy(i => i.UserID).Skip(skip).Take(take).ToList(); UserInfo在预处理列表上构建. 再次,在客户端执行所有操作. // Test 7 // VERY LONG. It tooks all records first and construct // UserInfo one by one before doing the skip and take var list = from usr in dbase.userinfoes.AsEnumerable() select new UserInfo(usr); 再次,在客户端执行所有操作. UserInfo在预处理列表上构建. 我在所有这些测试中都注意到了一个区别,那就是你调用UserInfo实例的构造函数的地方.在性能良好的地方,你推迟尽可能晚地构建UserInfo的实例(在执行命令,执行,跳过操作之后),而当性能不好时,你需要预先构建UserInfo实例,在进行这些操作之前(通常会对UserInfo构造函数进行更多调用). 也就是说,似乎您的性能问题可能存在于UserInfo类的构造函数中,而不是LINQ中.通常,当您让 虽然没有看到构造函数代码,但这是不可能的,但是你的数字肯定表明问题存在于那里,而不是在LINQ中. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |