大量数据如何做分页处理
本文分享自华为云社区《应用中大量数据的分页处理》,作者:码乐。
简介
大批量数据的展示一直被视为一个必须要解决的问题。 一个经典的思想就是分批展示和处理它们。
1 查询时外键的处理
如果在django model 中模型使用了外键,通过on_delete 来定义关联操作。
CASCADE: 级联操作。如果外键那条数据删除了,这条数据也将被删除 PROTECT: 受保护,只要这条数据引用了外键的那条数据,旧不能删除外键数据,如果强行删除,Django框架将报错 SET_NULL: 设置为空,如果外键数据被删除,本条数据设置为空,前提是 可以设置本条数据为空 SET_DEFAULT: 设置默认值,如果外键数据删除了,设置这个数据的值为默认,前提是有默认值 SET()函数: 如果外键那条数据被删除,那么将会获取SET函数的值作为外键的值。Set()函数可以接受可调用对象,可调用对象的返回值作为结果设置回去。 DO_NOTHING: 不采取任何行为,一切看数据库级别的行为。
数据库层面的约束:
PESTRICT: 默认选项,如果要删除父表记录,如果子表有关联记录,则不允许删除 NOACTION:同上,首先检测外键 CASCADE: 父表delete,update时,子表关联操作 也进行 delete,update SET NULL:父表delete , update时,子表将关联记录外键字段设置为null,所以设计子表时不能 not null
这些外键的方法工具,可以帮助使用者处理多表关联查询任务。
1.1 如何在django中查询分页
在有分页查询的应用中,包括 LIMIT 和 OFFSET 的查询十分常见,而且几乎每个都会有一个 ORDER BY 子句。
如果使用索引排序的话将对性能优化十分有帮助,否则服务端需要做很多文件排序。
一个高频的问题是 offset 的值过大。如果查询类似 LIMIT 10000, 20,将会产生10020行,并将之前的10000行丢弃,这样的代价很高。
select * from table order by id limit 10000, 20;
很简单,该语句的意思就是查询10000+20条记录,去掉前10000条,返回后20条。
无疑该查询能够实现分页,但10000这位置的值越大,查询性能就越低,因为MySQL需要扫描全部10000+20条记录。
假设所有的页使用相同的频次访问,这样的查询将平均扫描一半数据表。为了优化他们,你可以在分页视图中限制最多可访问的页数,或者让大批量的查询更有效。
当一个表中有很多符合查询条件的数据的时候,我们往往不需要把他们全部一次性取出来,那样对查询效率或者服务器性能来说都会是一个极大的挑战:例如最简单的商城,假设商城中有一万个数据,但我们在前端可能只会每次看到一页.
select * from table where xxx="xxx" limit 10;
这表示查询符合条件的10个数据。
select * from table where xxx="xxx" limit 10 offset 10;
这表示分页,查询符合条件的第11到20的数据。
或者通过指定最大id去查询
select * from table where id > #max_id# order by id limit n;
该查询同样会返回后n条记录,却无需像方式1扫描前m条记录,但必须在每次查询时拿到上一次查询(上一页)的最大id(或最小id),是比较常用的方式。
当然该查询的问题也在于,如果最大id不是连续的,则我们不一定能拿到这个id,比如当前在第3页,需要查询第5页的数据,就不行了。
或者通过子查询,先筛选前10000个,找到最大id,然后选择剩余的20个符合要求的
select * from table where id > (select id from table order by id limit m, 1) limit n;
该查询同样是通过子查询扫描字段id, 因为它不需要进行表的关联,而是一个简单的比较,在不知道上一页最大id的情况下,是比较推荐的用法。
左右连接的方式本身性能可能更差。
还有如下子查询、连接表,加索引快速定位元组,然后再读取元组
SELECT * FROM table WHERE id <= (SELECT id FROM table ORDER BY id DESC LIMIT (page-1)*pagesize ORDER BY id DESC LIMIT pagesize)
rest_framework 内建了分页的操作模块,让我们来应用到具体函数即可 employee/views.py
from rest_framework.pagination import PageNumberPagination @api_view(['GET', 'POST']) @permission_classes([CustomPermission]) def blog_api_view(request): """""" if request.method == "GET": paginator = PageNumberPagination() # paginator.page_size = 1 setting we display only 1 item per page. paginator.page_size = 2 task_objects = EmployeeSign.objects.all() result = paginator.paginate_queryset(task_objects, request)
如果不使用分页,将显示全部的消息在同一个页面
serializer = TaskSerializer(result, many=True) return Response(serializer.data)
访问分页数据.默认接口http://127.0.0.1:2001/api/tasks/ 就是分页1
http://127.0.0.1:2001/api/tasks/?page=1 #2,3,4...
2 小结
再重复一次,在有分页查询的应用中,包括 LIMIT 和 OFFSET 的查询十分常见,而且几乎每个都会有一个 ORDER BY 子句。如果使用索引排序的话将对性能优化十分有帮助,否则服务端需要做很多文件排序。
一个高频的问题是 offset 的值过大。如果查询类似 LIMIT 10000, 20,将会产生10020行,并将之前的10000行丢弃,这样的代价很高。
假设所有的页使用相同的频次访问,这样的查询将平均扫描一半数据表。
为了优化他们,你可以在分页视图中限制最多可访问的页数,或者让大量的查询更有效。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
详解Java Chassis 3与Spring Cloud的互操作
本文分享自华为云社区《Java Chassis 3技术解密:与Spring Cloud的互操作》,作者: liubao68。 Java Chassis 3一个很重要的设计原则:利用架构的韧性设计来解决兼容性问题。 比如通过引入微服务网关,来解决不同语言、不同框架、遗留系统之间的互操作问题。 本文在这个架构原则基础上,讨论一个更加细粒度的互操作问题,并借此解密Java Chassis3在运行时设计依赖上的技术细节。 首先,我们描述一个互操作的场景和假设。 Spring Cloud和Java Chassis应用同时注册到注册中心。引入了Spring Cloud Gateway作为网关,网关也注册到注册中心。 Spring Cloud微服务和Java Chassis微服务相互调用。它们彼此作为消费者的时候,不需要感知对方是不同的框架,做到透明调用。 从技术原理上梳理下上述互操作需要满足的条件: Spring Cloud和Java Chassis需要有相互认识的注册信息。核心包括:应用名称、服务名称、地址信息和格式等。 需要的共同注册中心越少,越容易对注册中心和客户端进行选型。 在本例子中,我...
- 下一篇
ES6生成器,看似同步的异步流程控制表达风格
本文分享自华为云社区《3月阅读周·你不知道的JavaScript | ES6生成器,看似同步的异步流程控制表达风格》,作者: 叶一一。 生成器 打破完整运行 JavaScript开发者在代码中几乎普遍依赖的一个假定:一个函数一旦开始执行,就会运行到结束,期间不会有其他代码能够打断它并插入其间。 ES6引入了一个新的函数类型,它并不符合这种运行到结束的特性。这类新的函数被称为生成器。 var x = 1; function foo() { x++; bar(); // <-- 这一行在x++和console.log(x)语句之间运行 console.log('x:', x); } function bar() { x++; } foo(); // x: 3 如果bar()并不在那里会怎样呢?显然结果就会是2,而不是3。最终的结果是3,所以bar()会在x++和console.log(x)之间运行。 但JavaScript并不是抢占式的,(目前)也不是多线程的。然而,如果foo()自身可以通过某种形式在代码的这个位置指示暂停的话,那就仍然可以以一种合作式...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 2048小游戏-低调大师作品
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS关闭SELinux安全模块