LinQ to SQL Skip分页效率问题

zhoul_831 2017-09-14 03:43:07
LinQ to SQL对获取到的数据进行分页显示时,使用的是
int COUNT_IN_ONE_PAGE = 10;
var items = db.Students;
items = items.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE)
在pageNum较小时,耗时在3000毫秒左右,但是
当pageNum较大,例如1200,则需要19000+毫秒,这个时间让页面等待很长时间,
请问有什么办法能够提高速度么?让pageNum在1200时,也能在3000毫秒左右处理完成。
...全文
1990 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_15148111 2017-10-14
  • 打赏
  • 举报
回复
db.Students.Skip((pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE);
丰云 2017-09-28
  • 打赏
  • 举报
回复
尼玛,skip里面居然放了委托。。。。 唉。。。。
丰云 2017-09-28
  • 打赏
  • 举报
回复
引用 楼主 zhoul_831 的回复:
LinQ to SQL对获取到的数据进行分页显示时,使用的是 int COUNT_IN_ONE_PAGE = 10; var items = db.Students; items = items.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE) 在pageNum较小时,耗时在3000毫秒左右,但是 当pageNum较大,例如1200,则需要19000+毫秒,这个时间让页面等待很长时间, 请问有什么办法能够提高速度么?让pageNum在1200时,也能在3000毫秒左右处理完成。
分页没有排序字段,我还头一次见!!!!! 就算现在的新生代程序员不学数据库,不了解索引优化,但ef分页的基本用法总该是要看看的吧!!!
  • 打赏
  • 举报
回复
不要单纯按照学习(其实跟分不清楚真懂还是抄袭)的方式设计程序,我们看一个程序员实际的开发能力,其实看调试、测试,而不是只看编程。那么对这个问题,你肯定首先要贴出来发送给 SQL Server 的最终的 sql 查询命令语句,只有当一个返回几十行数据(一页数据)的查询需要执行20秒钟时才应该纠结数据库方面的设计问题(例如索引、表结构)问题。重点是要自动自觉地贴出真实的 sql 语句。
  • 打赏
  • 举报
回复
你需要了解真实的、SQL Server数据库执行的查询。数据库只应该返回一页数据,而不能返回大量垃圾数据到内存。
  • 打赏
  • 举报
回复
引用 16 楼 xiaoxiangqing 的回复:
要看下生成的语句,
是的! 了解需要如何调试关键节点,胜过只知道写代码。
  • 打赏
  • 举报
回复
实在一点还是写存储过程吧
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 13 楼 starfd 的回复:
on p.id equals q.StudentID orderby p.time descending 先确认你的join有没有索引 然后确认你的time有没有索引
time有索引,Join的值没有索引,然后刚才看了一下, Join的值因为建表的时候类型写成了nvarchar(max),所以现在没法建索引了
  • 打赏
  • 举报
回复
on p.id equals q.StudentID orderby p.time descending 先确认你的join有没有索引 然后确认你的time有没有索引
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 11 楼 hanjun0612 的回复:
是在不行,就写动态sql var q=db.database.sqlquery<Students>(sql语句);
最后没办法的时候再这么干吧,因为动态条件挺多,用SQL语句来写太长而且不好维护
正怒月神 2017-09-14
  • 打赏
  • 举报
回复
是在不行,就写动态sql var q=db.database.sqlquery<Students>(sql语句);
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 9 楼 caozhy 的回复:
[quote=引用 8 楼 zhoul_831 的回复:] [quote=引用 5 楼 caozhy 的回复:] 这条linq取决于你对应的provider的翻译,如果数据库支持row number,那么就很快,否则就很慢。
我是用的SQL Server 2008 版本,这个对row_number用法支持么?[/quote] 用sql server profiler(sql server management studio的tools菜单下有)拦截调用的sql,看下就知道了。[/quote] 刚才查了一下,是支持的,但是还是慢,我google上查了一下说是因为Skip的时候,会根据我的排序遍历一遍,所以时间会长,Linq官方没有什么解决办法吗?
threenewbee 2017-09-14
  • 打赏
  • 举报
回复
引用 8 楼 zhoul_831 的回复:
[quote=引用 5 楼 caozhy 的回复:] 这条linq取决于你对应的provider的翻译,如果数据库支持row number,那么就很快,否则就很慢。
我是用的SQL Server 2008 版本,这个对row_number用法支持么?[/quote] 用sql server profiler(sql server management studio的tools菜单下有)拦截调用的sql,看下就知道了。
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 5 楼 caozhy 的回复:
这条linq取决于你对应的provider的翻译,如果数据库支持row number,那么就很快,否则就很慢。
我是用的SQL Server 2008 版本,这个对row_number用法支持么?
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 6 楼 duanzi_peng 的回复:
[quote=引用 4 楼 zhoul_831 的回复:] [quote=引用 2 楼 duanzi_peng 的回复:] linq to sql 会将最终的语法转换成sql语句 由数据库引擎执行。 var items = db.Students; items = items.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE) -》这两段代码,每次进行分页操作都会将所有的Students数据存到匿名变量里,改成: var list = db.Students.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE); 测试 PS:个人观点,欢迎指正。
您好,谢谢你的回复,我在改成如您所说情况之后,编译出错了 是不是我哪里没有写好?[/quote] 你贴的代码是自己写的么?,skip 接收的是一个int类型,不需要匿名委托。[/quote] 是刚才看到你的回复后照样子改的
exception92 2017-09-14
  • 打赏
  • 举报
回复
引用 4 楼 zhoul_831 的回复:
[quote=引用 2 楼 duanzi_peng 的回复:] linq to sql 会将最终的语法转换成sql语句 由数据库引擎执行。 var items = db.Students; items = items.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE) -》这两段代码,每次进行分页操作都会将所有的Students数据存到匿名变量里,改成: var list = db.Students.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE); 测试 PS:个人观点,欢迎指正。
您好,谢谢你的回复,我在改成如您所说情况之后,编译出错了 是不是我哪里没有写好?[/quote] 你贴的代码是自己写的么?,skip 接收的是一个int类型,不需要匿名委托。
threenewbee 2017-09-14
  • 打赏
  • 举报
回复
这条linq取决于你对应的provider的翻译,如果数据库支持row number,那么就很快,否则就很慢。
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 2 楼 duanzi_peng 的回复:
linq to sql 会将最终的语法转换成sql语句 由数据库引擎执行。

var items = db.Students;
items = items.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE)
-》这两段代码,每次进行分页操作都会将所有的Students数据存到匿名变量里,改成:
var list = db.Students.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE); 测试


PS:个人观点,欢迎指正。


您好,谢谢你的回复,我在改成如您所说情况之后,编译出错了


是不是我哪里没有写好?
zhoul_831 2017-09-14
  • 打赏
  • 举报
回复
引用 1 楼 starfd 的回复:
你比如的例子不对吧,如果按你这个,没按照任何条件查询过滤,那么直接就是聚集索引,不可能那么慢 你应该查的是你的索引设置问题
的确没有条件查询过滤,不过有一次内连接,然后按照入学时间排序了,大概语句是: var item = var items = (from p in m_db.student join q in m_db.Teacher on p.id equals q.StudentID orderby p.time descending select new Info { } 原来的语句因为设计到了公司的内容,不方便直接给出来,我给出的算是一个类似的情况。
exception92 2017-09-14
  • 打赏
  • 举报
回复
linq to sql 会将最终的语法转换成sql语句 由数据库引擎执行。 var items = db.Students; items = items.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE) -》这两段代码,每次进行分页操作都会将所有的Students数据存到匿名变量里,改成: var list = db.Students.Skip(() => (pageNum - 1) * COUNT_IN_ONE_PAGE).Take(COUNT_IN_ONE_PAGE); 测试 PS:个人观点,欢迎指正。
加载更多回复(1)
LINQ to SQL语句(1)之Where 2 Where操作 2 1.简单形式: 2 2.关系条件形式: 2 3.First()形式: 3 LINQ to SQL语句(2)之Select/Distinct 3 1.简单用法: 4 2.匿名类型 形式: 4 3.条件形式: 5 4.指定类 型形式: 6 5.筛选形式: 6 6.shaped形式(整形类型): 6 7.嵌套类型形式: 7 8.本地方法调用 形式(LocalMethodCall): 7 9.Distinct形式: 8 LINQ to SQL语句(3)之Count/Sum/Min/Max/Avg 9 1.简单形式: 9 2.带条件形 式: 9 1.简单形式: 10 2.映射形式: 10 3.元素 : 11 1.简单形式: 11 2.映射形式: 11 3.元素: 11 1.简单形式: 12 2.映射形式: 12 3.元素: 12 LINQ to SQL语句(4)之Join 13 Join操作符 13 1.一对多关系(1 to Many): 13 2.多对多关系(Many to Many): 14 3.自联接关系: 15 1.双向联接(Two way join): 15 2.三向联接(There way join): 16 3.左外部联接(Left Outer Join): 17 4.投影的Let赋值(Projected let assignment): 17 5.组合键(Composite Key): 18 6.可为null/不可为null的键关系 (Nullable/Nonnullable Key Relationship): 19 LINQ to SQL语句(5)之Order By 19 Order By操作 19 1.简单形式 19 2.带条件形式 20 3.降序排序 20 4.ThenBy 20 5.ThenByDescending 22 6. 带GroupBy形式 22 LINQ to SQL语句(6)之Group By/Having 23 Group By/Having操作符 23 1.简单形式: 23 2.Select匿名类 : 24 3.最大 值 25 4.最小 值 26 5.平均 值 26 6.求和 26 7.计数 27 8.带条件计数 27 9.Where限制 28 10.多列(Multiple Columns) 28 11.表达式(Expression) 29 LINQ to SQL语句(7)之Exists/In/Any/All/Contains 29 Exists/In/Any/All/Contains操作符 29 Any 29 1.简单形式: 29 2.带条件形式: 30 All 30 Contains 31 1.包含一个对象: 31 2.包含多个值: 32 LINQ to SQL语句(8)之Concat/Union/Intersect/Except 32 Concat/Union/Intersect/Except操作 32 Concat(连接) 32 1.简单形式: 33 2.复 合形式: 33 Union(合并) 33 Intersect(相交) 34 Except(与非) 34 LINQ to SQL语句(9)之Top/Bottom和Paging和SqlMethods 35 Top/Bottom操作 35 Take 35 Skip 35 TakeWhile 36 SkipWhile 36 Paging(分页)操作 36 1.索引 36 2.按唯一键排序 36 SqlMethods操作 37 Like 37 已编译查 询操作(Compiled Query) 38 LINQ to SQL语句(10)之Insert 38 插入(Insert)1.简单形式 38 2.一对多 关系 39 3.多对多关系 39 4.使用动态CUD重写(Override using Dynamic CUD) 40 LINQ to SQL语句(11)之Update 41 更新(Update) 41 1.简单形式 41 2.多项更改 41 LINQ to SQL语句(12)之Delete和使用Attach 42 删除(Delete)1.简单形式 42 2.一对多关系 42 3.推理删除(Inferred Delete) 43 使用Attach更新(Update with Attach) 43 LINQ to SQL语句(13)之开放式并发控制和事务 46 Simultaneous Changes开放式并发控制 46 开放式并发(Optimistic Concurrency) 46 1.Implicit(隐式) 48 2.Explicit(显式) 48 LINQ to SQL语句(14)之Null语义和DateTime 49 Null语义 49 1.Null 49 2.Nullable.HasValue 50 日期函数 50 1.DateTime.Year 51 2.DateTime.Month 51 3.DateTime.Day 51 LINQ to SQL语句(15)之String 51 字符串(String) 51 1.字符 串串联(String Concatenation) 52 2.String.Length 52 3.String.Contains(substring) 52 4.String.IndexOf(substring) 52 5.String.StartsWith (prefix) 53 6.String.EndsWith(suffix) 53 7.String.Substring(start) 53 8.String.Substring (start, length) 53 9.String.ToUpper() 54 10.String.ToLower() 54 11.String.Trim() 54 12.String.Insert(pos, str) 54 13.String.Remove(start) 55 14.String.Remove(start, length) 55 15.String.Replace(find, replace) 55 LINQ to SQL语句(16)之对象标识 56 对象标识 56 对象缓存 56 LINQ to SQL语句(17)之对象加载 57 对象加载延迟加载 57 预先加载:LoadWith 方法 58 LINQ to SQL语句(18)之运算符转换 59 1.AsEnumerable:将类型转换为泛型 IEnumerable 59 2.ToArray:将序列转换为数组 59 3.ToList:将序列转换为 泛型列表 59 4.ToDictionary:将序 列转化为字典 60 LINQ to SQL语句(19)之ADO.NET与LINQ to SQL 60 1.连接 61 2.事务 61 LINQ to SQL语句(20)之存储过程 63 1.标量返回 63 2.单一结 果集 64 3.多个可 能形状的单一结果集 65 4.多个结果集 70 5.带输出参数 79 LINQ to SQL语句(21)之用户定义函数 80 1.在Select中使用用户定义的标量函数 80 2.在Where从句中 使用用户定义的标量函数 81 3.使用用户定义的表值函数 83 4.以联接方式使用用户定义的表值函数 84 LINQ to SQL语句(22)之DataContext 85 创建和删除数据库 85 数据库验证 88 数据库更改 88 动态查询 89 日志 90 LINQ to SQL语句(23)之动态查询 90 1.Select 91 2.Where 92 LINQ to SQL语句(24)之视图 94 LINQ to SQL语句(25)之继承 96 1.一般形式 97 2.OfType形式 98 3.IS形式 98 4.AS形式 99 5.Cast形式 99 6.UseAsDefault形式 100 7.插入新的记录 101
1.简单形式: var q = ( from c in db.Customers select c.Phone ).Concat( from c in db.Customers select c.Fax ).Concat( from e in db.Employees select e.HomePhone ); 语句描述:返回所有消费者和雇员的电话和传真。 2.复合形式: var q = ( from c in db.Customers select new { Name = c.CompanyName, c.Phone } ).Concat( from e in db.Employees select new { Name = e.FirstName + " " + e.LastName, Phone = e.HomePhone } ); 语句描述:返回所有消费者和雇员的姓名和电话。 Union(合并) 说明:连接不同的集合,自动过滤相同项;延迟。即是将两个集合进行合并操作,过滤相同的项。 var q = ( from c in db.Customers select c.Country ).Union( from e in db.Employees select e.Country ); 语句描述:查询顾客和职员所在的国家。 Intersect(相交) 说明:取相交项;延迟。即是获取不同集合的相同项(交集)。即先遍历第一个集合,找出所有唯一的元素,然后遍历第二个集合,并将每个元素与前面找出的元素作对比,返回所有在两个集合内都出现的元素。 var q = ( from c in db.Customers select c.Country ).Intersect( from e in db.Employees select e.Country ); 语句描述:查询顾客和职员同在的国家。 Except(与非) 说明:排除相交项;延迟。即是从某集合中删除与另一个集合中相同的项。先遍历第一个集合,找出所有唯一的元素,然后再遍历第二个集合,返回第二个集合中所有未出现在前面所得元素集合中的元素。 var q = ( from c in db.Customers select c.Country ).Except( from e in db.Employees select e.Country ); 语句描述:查询顾客和职员不同的国家。 Top/Bottom操作 适用场景:适量的取出自己想要的数据,不是全部取出,这样性能有所加强。 Take 说明:获取集合的前n个元素;延迟。即只返回限定数量的结果集。 var q = ( from e in db.Employees orderby e.HireDate select e) .Take(5); 语句描述:选择所雇用的前5个雇员。 Skip 说明:跳过集合的前n个元素;延迟。即我们跳过给定的数目返回后面的结果集。 var q = ( from p in db.Products orderby p.UnitPrice descending select p) .Skip(10); 语句描述:选择10种最贵产品之外的所有产品。 TakeWhile 说明:直到某一条件成立就停止获取;延迟。即用其条件去依次判断源序列中的元素,返回符合判断条件的元素,该判断操作将在返回false或源序列的末尾结束 。 SkipWhile 说明:直到某一条件成立就停止跳过;延迟。即用其条件去判断源序列中的元素并且跳过第一个符合判断条件的元素,一旦判断返回false,接下来将不再进行判断并返回剩下的所有元素。 Paging(分页)操作 适用场景:结合Skip和Take就可实现对数据分页操作。 1.索引 var q = ( from c in db.Customers orderby c.ContactName select c) .Skip(50) .Take(10); 语句描述:使用Skip和Take运算符进行分页,跳过前50条记录,然后返回接下来10条记录,因此提供显示Products表第6页的数据。 2.按唯一键排序 var q = ( from p in db.Products where p.ProductID > 50 orderby p.ProductID select p) .Take(10); 语句描述:使用Where子句和Take运算符进行分页,首先筛选得到仅50 (第5页最后一个ProductID)以上的ProductID,然后按ProductID排序,最后取前10个结果,因此提供Products表第6页的数据。请注意,此方法仅适用于按唯一键排序的情况。 SqlMethods操作 在LINQ to SQL语句中,为我们提供了SqlMethods操作,进一步为我们提供了方便,例如Like方法用于自定义通配表达式,Equals用于相比较是否相等。 Like 自定义的通配表达式。%表示零长度或任意长度的字符串;_表示一个字符;[]表示在某范围区间的一个字符;[^]表示不在某范围区间的一个字符。比如查询消费者ID以“C”开头的消费者。 var q = from c in db.Customers where SqlMethods.Like(c.CustomerID, "C%") select c; 比如查询消费者ID没有“AXOXT”形式的消费者: var q = from c in db.Customers where !SqlMethods.Like(c.CustomerID, "A_O_T") select c; DateDiffDay 说明:在两个变量之间比较。分别有:DateDiffDay、DateDiffHour、DateDiffMillisecond、DateDiffMinute、DateDiffMonth、DateDiffSecond、DateDiffYear var q = from o in db.Orders where SqlMethods .DateDiffDay(o.OrderDate, o.ShippedDate) < 10 select o; 语句描述:查询在创建订单后的 10 天内已发货的所有订单。 已编译查询操作(Compiled Query) 说明:在之前我们没有好的方法对写出的SQL语句进行编辑重新查询,现在我们可以这样做,看下面一个例子: //1.创建compiled query NorthwindDataContext db = new NorthwindDataContext(); var fn = CompiledQuery.Compile( (NorthwindDataContext db2, string city) => from c in db2.Customers where c.City == city select c); //2.查询城市为London的消费者,用LonCusts集合表示,这时可以用数据控件绑定 var LonCusts = fn(db, "London"); //3.查询城市为Seattle的消费者 var SeaCusts = fn(db, "Seattle"); 语句描述:这个例子创建一个已编译查询,然后使用它检索输入城市的客户。

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧