分页功能设计(解决数据重复问题)

分页功能设计(解决数据重复问题),第1张

传统分页的话,一般只考虑传页数和每页数据条数这两个参数给后端,为了方便后面描述,我们给这个传参方式起个名字叫 传统分页 。这种传参方式对于静态数据(数据不会变动)的分页是没问题的,因为每条数据的顺序、数据的总量,都是不变的。

如果出现数据顺序变动或者数据总量变动的分页需求时,单纯的传page和limit已经不能解决了。

不同的需求需要显示的列表也不一样。关于列表分页我认为主要关系到两个方面, 总量 (列表头插入了新数据) 和 排列顺序 传统分页 总量不变,排列顺序不变 的列表下是没有任何问题的,但只要这两个要素其中一个是变化的, 传统分页 方式就会出现BUG(具体案例后面会讲到)。关于上面提到两个要素对应的需求举例:

现在有一个积分排行榜

假定每页显示3条数据,在某一时刻拿第一页数据时,得到 A、B、C三条数据。就在此时,用户D突然增加了100积分,最新的排行榜情况变成了

传统分页 的情况下,获取第二页数据时,即从当前排行榜第四条数据开始获取,得到 C、E,用户看到的数据就变成 A、B、C、C、E。这里C出现了2次,而且D消失了。这就是传统分页用在 数据排列顺序会改变的列表 时会出现的问题,因为列表顺序改变导致出现重复数据和丢失数据。

这种 总量不变,排列顺序改变 的分页问题我能想到的暂时有两种方案解决:一次性取出、排行榜快照、通过变动记录表拿数据。

这里说的一次性取出是针对类似“top100”这种取有限条数的需求。在比较简单的列表数据结构下一次性取出100条数据对服务器性能来说问题不大,但是在复杂数据结构下(涉及关联多个表、数据格式化、数据处理等)一次性处理100或更多的数据肯定是糟糕的做法。

排行榜主要的分页问题是 影响排名的字段的值在不断变化导致列表顺序不断改变 ,我们现在可以一次性取出整个列表但是又担心复杂的数据结构导致服务器性能问题。那如果我们把整个功能拆分一下,用异步的思想来做这个功能设计如何呢。

我们分两个接口来做这个功能:获取排行榜列表和获取用户排行榜数据。

获取排行榜列表接口 一次性取整个排名列表的用户ID和排名相关的字段数据,这样就保证了整个列表的排序是不变的同时,又不增大服务器性能。

获取用户排行榜数据接口 负责取排行榜要显示的用户的其他数据,这个接口接受多个用户ID的作为参数。这个接口做了类似分页的功能,前端每次从排行榜中按分页的方式按顺序取部分用户ID,然后通过这个接口获取具体数据显示给用户。

下面以例子的方式来做具体说明:

这是一个 积分排行 top100

这里的排行条件是 积分 ,那我们的 获取排行榜列表接口 只需要取“用户ID”和“积分”即可,剩下的 “昵称”、“胜率”等数据通过 获取用户排行榜数据接口 获取。

前端先请求 列表接口,获取到一下数据:

然后根据这个列表数据,先取前10条的用户ID:5、12、60、2、77… 去请求 获取用户排行榜数据接口,把获得的用户数据填充到排行榜中。当用户下滑加载更多数据时再去列表取在11-20的用户ID重复上面的 *** 作。

如果是 top100 的需求,这个方案是比较 推荐 的,因为没有性能和储存空间上的额外消耗。

因为考虑到主要问题出在排列顺序是变化的,而且通过其他APP也有看到过按时刷新的排行榜,所以想到了用快照的方式来解决。

可以通过写一个定时脚本,每5分钟生成一次排行榜的快照信息并存下来。接口请求时直接从快照中取数据,这一定程度上解决了列表排序一直在变化问题。这里之所以说只解决了一定程度,是因为在每次刷新快照数据的时候,可能有用户刚好卡在这个时间点之间去请求(刷新快照前用户请求了第一页数据,刷新快照后用户请求第二页,这就出现 传统分页 同样的问题了)。

可以通过在快照中加上 版本号 来解决问题。例如在生成快照的时候以当前时间戳作为版本号跟快照数据一起保存,同时需要系统保存多份快照数据以便用户获取旧快照数据。请求接口时默认拿最新版本的快照,如果接口传入了版本号就拿对应版本号的快照数据。

每个完备的系统都会有数据变动的记录表,用于追踪数据变动和 *** 作明细。记录变记录着数据每次变动前后的变化和变动时间,这一特性为使得数据的每次变动都有迹可循,我们就是利用这一点来做排行榜的分页。

我们分页出问题的地方就是因为数据在不断变化导致排序不停改变。上面说到每次数据变动都会有记录,那我们只需要根据某一时刻之前用户的数据来做排名,是不是就解决数据不断变动这个问题。文字表达可能不太直观,看下面的数据演示应该能比较好理解。

假定用户 A、B、C 初始默认都是100积分

表: score_log

假定在03分的时候请求了数据,通过下面的SQL语句就可以拿到03分之前的数据排行。

得到第一页数据:

第二页数据:

关于这种方式的请求,前端需要记录发起第一次请求时的时间,以后每页的请求都带着这个时间。

评论列表一般按照倒叙排列,而且顺序不变。因为是倒叙排列,所以最新的用户评论会放在最顶部,这就会导致问题了。我们还是用实际例子来说。

假定每页拿3条数据,此时请求第一页,得到ID分别5、4、3的评论。在请求第二页之前,突然又来了一条留言,此时列表变成:

传统分页 方式,此时获取第二页会得到ID 3、2、1,这里ID 3 就重复取出来了。

这个问题的解决方案相比排行榜列表分页问题简单而且易懂。评论ID是一个自增的int字段,新的评论ID总是比旧评论ID要大,利用这一点我们可以很好的解决问题。

接口传参:

limit 就不用作解释,说一下lastid。当获取第一页数据时,因为没有上一页所以 lastid 传空或者不传,此时服务器取最新的数据即可。获取第二页数据时,lastid 传第一页最后一条数据的ID,此时服务器取 ID < lastid 的数据,这就保证最新的评论不会影响到当前用户的分页。

这里做一个扩展,我们有时候看到有的页面在刷新的时候,会提示有多少条新的未查看评论(即列表头新的数据),这个功能的实现原理跟我们上面分页的原理差不多。在获取第一页数据时,把第一页的第一条数据ID保存下来,后面请求每一页时都把第一条ID( firstid )带上,服务器每次查 ID > firstid 的数据条数,如果大于0即表示有新的评论。

首先说一下,下面提供的方法我自己也不满意(如果有什么想法欢迎大家留言交流)。参考了微博的评论排序也存在上面说到的分页bug,感觉要完美解决这个需求的分页问题花费的代价(实现时间、服务器性能、存储空间等)大于功能本身,所以建议读者选择比较折中的方式来处理(与产品或上级沟通实现的难度)。

这个需求相比评论列表,多了点赞的功能,列表按点赞数量倒叙排列。先说一下不严谨情况下这个分页的实现方式:

这种方式会有两个问题:

我们可以沿用上面讲到的两个需求的解决方案。在解决列表排序问题上,我们可以沿用排行榜的 通过变动记录表拿数据 方式,增加一个表去记录评论的点赞变动记录(用空间换效率)。

表结构:

分页用到的查询语句:

1、用户需求分析

用户需求分析是整个APP开发流程中最重要的一环,相当于企业中决策者的地位,一款APP成功与否也尽数决定于此。此处的用户需求分析是基于用户的要求进行APP功能的梳理。注意此处是用户,因为很多公司要求开发出来的APP是给其用户使用,因此在整理APP开发需求时,不仅要了解开发企业的需求,也要了解其客户群体的需求。最终将这些需求进行梳理、分类,整理出大体的APP功能框架。此过程中需要与客户密切的进行沟通,力求做到没有任何疑问,以免开发出不实用的APP。

2、产品原型设计

在进行一轮用户需求分析之后,将整理出来的需求分类、整理、排序成功能结构模块,此时可以利用现有的功能模块搭建一个简单的产品原型。产品原型类似于一个APP产品的草图,将基本的功能结构展示给客户,可以借助产品原型设计软件模拟出相似的APP产品。将此产品原型与客户进行确认,确认完毕就可进入下一环节的开发。

3、UI视觉设计

在拥有APP产品原型草图结构之后,UI设计师们开始对APP的界面进行设计美化,根据APP的表现内容进行版面结构设计,然后对每一块区域进行相应的配色,并绘制每个功能菜单的图标及其他页面元素的设计,最终设计出所有的APP界面效果图。此过程与客户进行沟通,参考客户建议进行设计。

4、数据库搭建

按照需求分析整理出来的功能数据处理情况,建立合理的数据库表结构,优化数据算法,提升数据的处理效率,保证在使用APP的过程中数据的安全性、准确性、稳定性和及时性。

5、服务端开发

APP应用的核心处理过程均是由服务器端的程序完成的,客户端的APP仅仅只需要进行收发数据即可。由于用户的移动端设备硬件配置和存储容量有限,因此核心数据处理过程均是由服务器端进行运算处理的,这种方式也被称为云计算,服务器处理完成之后反馈给客户端APP。因此服务器端的程序开发极为重要,所有的功能均需要严格按照需求分析阶段整理的功能来进行开发。

6、iOS/Android客户端开发

1此时按照设计师设计的APP效果图进行开发客户端,主要是对设计效果图的代码实现,并写入功能调用的接口,连接服务器端,方便与服务器端的数据进行交互。根据Android和iOS的设备软硬件情况进行APP开发和优化,最终开发出与效果图一致的APP客户端。

7、APP程序测试

对已开发好的APP客户端进行全面的测试,此测试模拟用户正常使用以及非正常使用的情况,通常会导入一些测试数据来进行测试,将测试的结果进行记录,出现错误则返回到开发阶段进行修复,如果测试通过,则说明整体APP开发过程已经完成。将成品APP应用交给用户进行试用,用户满意之后进行下一步工作。

8、上传到应用商店

到此阶段一个APP开发已经完成,在完成签名验证之后,将开发好的客户端APP程序提交发布到各应用商店。iOS版本的APP提交到苹果的AppStore,安卓的提交到国内各大安卓应用商店。

9、APP的维护及更新

对上线之后的APP进行维护,收集用户反馈信息,及时修复APP应用中出现的错误(Bug)。如客户需要进行APP的功能更新时,则返回至需求功能整理阶段进行开发,新功能开发完成后经测试通过即可发布更新。

注意事项:

从最初与客户了解需求功能到最终的测试上线,一个完整的APP就被开发出来了。如同其他软件开发一样,APP的整个生命周期都是需要紧扣用户需求的,一旦脱离用户需求,就极可能开发出质量差、用户不认可的APP软件,这是许多APP开发企业需要高度重视的地方。

RDBMS 关系型DBMS

Record(记录) 同元组(Tuple)

Recovery control(恢复控制) 当时百事 将数据库还原到正确状态的过程

Rcursive relationship(递归关系) 一种关系 挡同一个实体在不同的角色中参与多次时就会出现递归关系 例如Staff Supervises Staff

redundant data(冗余数据) 在多个表中存储的重复数据

Referential integrity(参照完整性) 如果一个表中存在外健 则外健值必须匹配主表中的某些记录的候选键的值

Relation(关系) 一个关系是一张表 它也有列和行

Relational model(关系模型) 以表(或关系)的形式表示数据的数据模型

Relational database(关系数据库) 规范化表的集合

Relation(关系) 实体间有意义的关系

Relationship occurrence(关系出现) 两个实体出现之间的唯一可标识的联系

Requirements collection and ysis(需求收集于分析) 数据库应用程序生命周期的一个阶段 包括收集和分析数据库应用程序所要支持的关于公司的信息 并使用这些信息来标识新的数据库应用需求

Row(行) 同元组(Tuple)

Second normal form(第二范式) 一个已经是第一范式的表 同时满足所有的非主健列只能从构成主健的全部列中获得

Secondary index(二级索引) 在数据文件的非有序字段上定义的索引

Security(安全) 指防止数据库被非授权的用户访问 包括有意的和无意的 RDBMS通常提供两种类型的安全 数据安全和系统安全

Server(服务器) 为发出请求的客户提供服务的软件应用程序 参见两层/三层客户端 服务器体系结构

Simple attribute(简单属性) 只有一个组件的属性

Single valued attribute(单值属性) 对于一个实体出现只有一个值的属性

Specialization(特化) 通过标识用来区分实体间成员的特征来最大花实体间成员的差别的过程

Specialization hierarchy(特化层次结构) 同类型层次结构(Type hierarchy)

SQL(Structured Query Language 结构化查询语言) 一种用于RDBMS的非过程化数据库语言 换言之 你只需要指定你需要那些信息 而不需要指定如何得到这些信息 SQL已经被国际标准化组织(ISO)标准化了 因此SQL是定义和 *** 纵RDBMS的正式和实际上的标准语言

Strong entity(强实体) 一个不依赖于其他实体的主健的存在而存在的实体

Subclass(子类) 为(超类)实体中的某些出现并保持特定属性和关系并有不同角色的实体

Superclass(超类) 为实体中的所有出现保存公共属性和关系的实体 可参见特化和泛化

Superkey(超键 ER模型) 一个属性或属性集 诶译的标识了每个实体地出现

Superkey(超键 关系模型) 一个列或者列集 唯一的标识了表中地一个记录

System catalog(系统目录) 保存关于数据库地结构 用户 应用程序等信息地数据

System definition(系统定义) 数据库应用声明周期重的一个阶段 包括定义数据库应用程序以及他的主要用户视图地范围和边界

System security(系统安全) 在系统级保护数据库地访问和使用 不如用户名和密码

Table(表) 同关系(relation)

Ternary relationship(三元关系) 三个实体间的关系 例如panch staff和member之间的Registers关系

Testing(测试) 数据库应用生命周期的一个阶段 包括执行应用程序并有意地发现错误

Third normal form NF(第三范式) 一个已经是 NF和 NF的表 同时满足所有的非主健的列的值仅能从主健列得到 而不能从其他列得到

GL Third Generation Language(第三代语言) 一种过程化的语言 比如COBOL C C++ 它需要用户(通常是程序员)指定必须要干什么事情以及如何干这些事情

Three tier client server architecture(三层客户端 服务器体系结构) 由处理用户界面的客户和处理业务逻辑的应用程序服务器以及数据处理曾组成 而数据库服务器是用来来运行DBMS的

Top down approach(自顶向下方法 用于数据库设计) 一种设计方法 此种方法从定义系统的主要结构开始 然后将这些结构逐步细分成更小的单元 在数据库设计中 通过标识实体和数据间的关系开始这个顶层的步骤 然后逐步添加细节 比如你希望保存的关于实体和关系的信息(成为属性)以及在实体 关系和属性上的所有约束

Transaction(事务) 由用户和应用程序执行的一个动作或一系列动作 这些动作访问或修改数据库的内容

Transaction Processing Monitor TPM(事务处理监视器) 控制数据在客户端和服务器键转换的程序 以便为联机事务处理(OLTP)提供一个一致的环境

Transitive dependency(传递依赖) 假设A B C是表中的列 如果B依赖于A(A >B) 并且C依赖于B(B >C) 则C通过B传递而依赖于A(假设A不依赖于B或C) 如果在主健上存在一个传递依赖 则此表就不是 NF的 必须从表中去掉传递依赖以达到 NF的要求

Tuple(元组) 关系中的一行记录

Two tier client server architecture(两层客户端 服务器体系结构) 由处理主要业务和数据处理逻辑以及与用户的接口的客户端应用程序和管理和控制数据库访问的服务器程序组成

Type hierarchy(类型层次结构) 一个是提以及它的子类和他们的超类 等等

UML(Unified Modeling Language 统一建模语言) 在 世纪 年代和 年代引入的诸多面向对象分析与设计方法重的一种较新的方法

Update anomalies(更新异常) 当用户视图更新一个包含冗余数据的标识可能引起的不一致 有三种类型的异常 插入 删除和更新

User view(用户视图) 从特定的作业(比如经理或管理者)角度或业务应用领域(比如市场 职员或库存控制)定义的数据库应用的需求

View(视图) 一个 虚拟底表 它不实际存在数据库中 但他由DBMS从现有底它所涉及的基本表中产生

View integration approach(视图综合法 用于数据库设计) 每个用户视图的需求 用来构建代表用户试图底独立数据模型 在数据库设计阶段 结果数据库模型被合并成一个更大的模型

lishixinzhi/Article/program/SQL/201311/16197


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/13067225.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-30
下一篇 2023-05-30

发表评论

登录后才能评论

评论列表(0条)

保存