场景:

用户打开一页面,向服务端请求10条最新数据(第1页), 然后用户继续停留在这个页面,5分钟后,用户请求第2页数据。 在这5分钟时间内, 服务器中新增加了数据。

问题:

如果服务器中数据是按 权重和ID倒序排序的( SELECT ... order by weight DESC, id DESC LIMIT 0, 10), 传统的分页处理方式,通过将下一页数据时发送第几页( http://host/news?page=2), 那么服务端中使用 select ... limit ... offset 的话, 像上述所描述的场景,拿到的第2页数据会有部分和第一页的相同。

请问,有什么方法解决第2页不拿重复数据的问题?

请求下一页的数据时,不只传页码,再加上上一页请求的最后那行数据的id和weight的值也可能不行。如果请求下一页的数据, 将上一页及上一页之前的所有id提交到服务器, 如果页数比较多的话,数据就比较大了。 因是App应用,想数据尽可能的少。

2011-03-14 20:07:00

13 Answers

既然是ID排序可以在分页后跟当前页面最后一个ID为参数,但你的SQL让这么做变得复杂
首先生产环境下前端是不需要如此精确的,例如淘宝,amazon都会有一页显示50条数据,但可能只显出48条,第二页重复第一页商品的情况更是常见,这不重要,没必要为此增加逻辑复杂度
新增商品后,第二页显示当前正确的第二页还是专为客户端显示一个该客户端的第二页这是皆有正确性的选择

如果必须这么做,只能将weight与id传入URL参数,然后where weight<xx&&id<0

2011-03-14 21:46:39

感觉不可避免吧,一般这样的情况是可以忽略的,如果真想不重复的话,我有几个思路:

1,缓存数据,比如取100条数据,按照每页显示数量分割,使用memcache分页,如果又浏览到第一页,重新缓存数据,或者直接来个过期时间。

2,使用nosql数据记录最新的数据,最新数据达到一定数量后同步到数据库,这样可以减少一些重复的情况,完全不重复也做不到。

3,每次访问第一页时,将第一条数据的id记录即:maxId(记录方式可以是session),那么浏览其他页面的slq可以写为:

SELECT ... where id < maxId order by weight DESC, id DESC LIMIT ofset, 10

同样再次浏览到第一页时,重新更新这个值。。

2011-03-15 03:00:35

因为看到你说你的是一个APP应用,你的瓶颈在于已经打开的页面数据可能会被新增的数据翻页时被推到后面,其实我觉的如果是APP应用的话,就不要采用常规的分页,比如翻页的时候记录位置是还是按照上一页打开也数据的最后id为翻页的起始id,通过比如用户滑动屏幕到底部时触发下一页的加载,同时的新的数据可以通过下拉屏幕触发最新数据的加载,其实这些已经是很多手机客户端读取数据的策略了,比如微博类,空间说说类的,(如果是网页形式的,触发实现困难的话可以通过论坛类似的新消息提示来提示用户来叠加加载新数据...)其实就是相对翻页,而不是我们普通均等分页,这样的话,类似select ... limit ... offset 这样的语句就需要修改一下查找方式了...就像你后面手的,通过记录id来进行。

2011-03-15 01:09:56

可以使用生成静态页的方式避免类似情况,类似于缓存机制!

2011-03-15 08:44:35

一般情况下这是可以忽略的,当打开第一页后,数据源更新了,再打开第二页,势必会在第二页上产生与第一页重复的几笔数据。如果,必须去控制的话,倒是可以建议你采用断开连接后查询,当进入页面后读出数据并断开连接,只要不是重新进入页面就不会去与数据库同步,在之前,公司给一个政府服务部门做系统时曾用到过,不过效果不好,在二次开发时去掉了。

2011-03-15 10:21:40

不知道具体的分页内容是什么。
如果类似于新浪微博之类的消息,实时查询数据库的方式是不可取的。可以考虑建立为每个用户建立队列的方式,新数据就是未读数据。为每次请求生成不同条数的内容来处理。
如果是普通数据。
动态修改第一个页面的缓存个数即可。

2011-03-15 12:08:23
您不能回答该问题或者回答已经关闭!

相关文章推荐

  • C#实例解析适配器设计模式

    将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作

  • C#中using指令的几种用法

    using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到

  • C#协变和逆变

    “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型,“逆变”则是指能够使用派生程度更小的类型

  • C#运行时相互关系

    C#运行时相互关系,包括运行时类型、对象、线程栈和托管堆之间的相互关系,静态方法、实例方法和虚方法的区别等等

  • 使用托管C++粘合C#和C++代码(二)

    本文实现一下C++代码调用C#代码的过程。我构造一个简单并且直观的例子:通过C++ UI 触发C# UI.

  • C#开发高性能Log Help类设计开发

    项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多

  • C#开发中的反射机制

    反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等

  • Async和Await使异步编程更简单

    C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作

  • 使用托管C++粘合C#和C++代码(一)

    C#在xml读写,数据库操纵,界面构造等很多方面性能卓越;C++的效率高,是底层开发的必备武器

  • C#基础概念之延迟加载

    延迟加载(lazy load)是Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作

  • C#中的索引器的简单理解和用法

    C#中的类成员可以是任意类型,包括数组和集合。当一个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作

  • 深入C# 序列化(Serialize)、反序列化(Deserialize)

    C#中的序列化和反序列化,序列化是.NET运行时环境用来支持用户定义类型的流化的机制