深度分页问题优化方案

问题原因

Mysql使用select * from table limit offset, rows分页在深度分页的情况下, 性能急剧下降。

例如:select * 的情况下直接⽤limit 600000,10 扫描的是约60万条数据,并且是需要回表 60W次,也就是说⼤部分性能都耗在随机访问上,到头来只⽤到10条数据(总共取600010条数据只留10条记录)

优化方案

前端方案:业务层面限制跨度比较大的跳页

提供2种风格分页器供用户选择

  1. 标准分页器,展示最后一页和跳转指定页输入框
    image.png
  2. 简单分页器
    image.png

参考
百度方案: 不展示最后一页和直接跳转指定分页的输入框
image.png
Google方案:只展示查看下一页的按钮
image.png

界面设计器选表格/画廊的属性面板提供分页器风格的属性下拉选择

image.png

xml示例
<!-- 表格使用的标准分页器 --> <view type="TABLE" paginationStyle="SIMPLE"> <!-- fields --> </view> <!-- 画廊使用默认的标准分页器 --> <view type="GALLERY" paginationStyle="STANDARD"> <!-- fields --> </view>

后端方案

  1. 使用索引:确保数据库表中的相关字段上创建了适当的索引。索引可以加快查询速度,特别是在处理大数据量时。

  2. 分批查询:将大数据分成多个较小的批次进行查询,而不是一次性查询全部数据。可以通过限制每次查询的数据量和使用合适的偏移量来实现分批查询,例如使用LIMIT和OFFSET子句。

  3. 基于游标的分页:使用基于游标的分页技术,而不是传统的偏移分页。游标分页是通过记录上一次查询的游标位置,在下一次查询时从该位置开始获取新的数据,避免了大偏移量的影响。这可以通过数据库自身的功能(例如MySQL的CURSOR)或使用第三方库来实现。

  4. 缓存数据:如果数据变化较少,可以考虑将查询结果缓存到内存中,以避免频繁地查询数据库。这样可以提高页面相应速度,并减轻数据库负担。缓存的数据应该根据业务需要及时更新。

  5. 数据预处理:如果查询结果经常需要进行复杂的计算或处理,可以考虑提前对数据进行预处理并缓存结果,以减少每次查询的计算负担。

  6. 数据库优化:针对具体数据库系统,可以根据实际情况进行数据库调优。例如,合理设置数据库连接池大小、调整数据库参数等。

  7. 分布式存储和计算:对于非关系型数据库或分布式存储系统,可以考虑使用分布式存储和计算方案,将数据分散存储在多个节点上,并通过计算节点并行处理查询请求,以提高性能和可伸缩性。

参考链接

MySQL深分页场景下的性能优化

Oinone社区 作者:原创文章,如若转载,请注明出处:https://doc.oinone.top/other/75.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
的头像
上一篇 2023年6月20日 pm4:07
下一篇 2023年11月2日 pm1:58

相关推荐

  • 组件介绍

    在设计页面时,页面中的所有内容均是由组件组成,每个组件有不同的属性,可以灵活的对每个组件的属性进行设置,以满足业务场景。 组件分为四类,分别是布局、字段、动作、数据 1. 布局 布局类组件主要用于页面的样式排版。 分组:类似一个容器,可以把业务含义相近的内容放在这个分组容器内。 选项卡:类似一个容器,每个选项卡可以添加多个选项页,可以把业务含义相近的内容放在选项卡的选项页容器内。 2. 字段 字段型组件是常用,也是用于支撑页面的主要组件类,每个字段型组件都对应一个模型字段。 单行文本:常用于记录名称、身份证号或其他普通的文字内容。 多行文本:常用于记录字数较多的文字,如意见、复杂备注等。 整数:常用于输入整数的天数、数量等,如果会出现小数,请使用小数组件。 小数:常用于输入金额、单价等,会出现小数的数值。 下拉单选:从多个选项中下拉选择一个数据,作为数据值。选项可以是关联模型的数据,也可以是数据字典或布尔型开关。 下拉多选:从多个选项中下拉选择多个数据,作为数据值。选项可以是关联模型的数据,也可以是数据字典。 开关:常用于只有是否两种对立选项的选择。 单选框:常用于在直接展示的选现中单选一个值,例如选择性别。 复选框:常用于在直接展示的选现中多选一个值,例如选择爱好、选择课程等。 富文本编辑器:一种可内嵌于浏览器,所见即所得的文本编辑器,类似于Office Word 的编辑功能,常应用于篇幅较长的说明性文字,支持改变字体样式、插入图片等。 年份:常用于选择出身年份、一项计划的年份等。 日期:常用于选择颗粒度到日期的Date类型字段,例如出生日期、入职日期、入驻日期等。 日期时间:常用于选择颗粒度到时间的DateTime类型的字段,例如下单时间、发货时间、审批时间等。 时间:常用于选择仅时间无日期的Time类型的字段,如设置规章中的上班时间、日志的提交时间等。 颜色选择器:应用于自定义颜色,如设置标签的颜色、设置产品的颜色属性、主题定制时选择色彩等。 文件上传:常用于上传附件、文件,例如Office文档、图片、视频、音频、其他格式的文件等。 图片上传:常用于上传记录的图片,例如上传身份证照片、头像、商品图片等。 标签:可输入保存多值,例如用户的标记标签。 3. 数据 与数据可视化设计器进行联动,可以选择自定义的图表或报表,在页面展示。 图表:可以选择数据可视化设计器中允许被引用的图表,展示在页面中 报表:可以选择数据可视化设计器中允许被引用的报表,展示在页面中

    Oinone 7天入门到精通 2024年6月20日
    1.4K00
  • 4.1.x版本更新说明-20230511

    版本号:4.1.x发布日期:2023.05.11更新要点:前端发布内容包括系统配置更新,修复界面设计器中表格和树表样式问题,统一处理HttpClientError异常,以及修复多选项卡首页初始化时出现两个选项卡的问题。后端发布内容包括RocketMQ支持ACL,解决应用绑定首页报错的bug,解决页面设计器编辑后导致layout丢失的问题。 1 发布概要 1.1 前端 发布内容: 系统配置 界面设计器修复【表格】-【树表】样式问题 统一处理HttpClientError异常 修复多选项卡首页初始化会出现两个选项卡的问题 1.2 后端 发布内容: RocketMQ支持acl 解决bug:应用绑定首页报错 解决bug:页面设计器编辑页面后,layout问题 2.最新版本包信息 !–平台基础jar包–> <pamirs.middleware.version>4.7.0</pamirs.middleware.version> <pamirs.k2.version>4.7.3.2</pamirs.k2.version> <pamirs.boot.version>4.7.7.5</pamirs.boot.version> <pamirs.framework.version>4.7.5.3</pamirs.framework.version> <pamirs.core.version>4.7.7.4</pamirs.core.version> <pamirs.distribution.version>4.7.4.1</pamirs.distribution.version> <pamirs.metadata.manager>4.7.3</pamirs.metadata.manager> <pamirs.lowcode.version>4.7.0</pamirs.lowcode.version> <!–设计器jar包–> <pamirs.designer.common.version>4.7.2</pamirs.designer.common.version> <pamirs.workflow.version>4.7.6.8</pamirs.workflow.version> <pamirs.flow.designer.base.version>4.7.3.1</pamirs.flow.designer.base.version> <pamirs.dataflow.designer.version>4.7.0</pamirs.dataflow.designer.version> <pamirs.workflow.designer.version>4.7.2</pamirs.workflow.designer.version> <pamirs.workbench.version>4.7.1</pamirs.workbench.version> <pamirs.model.designer.version>4.7.1.1</pamirs.model.designer.version> <pamirs.ui.designer.version>4.7.4.1</pamirs.ui.designer.version> <pamirs.data.designer.version>4.7.0</pamirs.data.designer.version> <pamirs.data.visualization.version>4.7.1</pamirs.data.visualization.version> <pamirs.eip.designer.version>4.7.1</pamirs.eip.designer.version> 如果您有任何问题、建议或反馈,请随时联系我们。为了获得最佳体验,建议请升级至最新版本。我们将继续努力改进产品,提供更好的服务。谢谢您的支持!

    2023年5月11日
    98000
  • O2M、M2O、M2M关系字段配置问题以及问题排查路径

    M2O关系字段 配置示例: @Field(displayName = “教师关联学生”) @Field.many2one @Field.Relation(relationFields = {“studentName”}, referenceFields = {“name”}) private Student students; 解析: 在这个多对一关系中,studentName为本模型的字段,name为Student的字段,这个多对一关系通过这两个字段关联起来。 在保存该关联关系时,会将name的值带到studentName里并保存在当前模型中(many) studentName字段必须是存储字段,因为在查询many的数据的时候是通过这个字段进行查询的。 name必须在关系模型即Student里面定义(one),studentName在本模型里面定义不定义都可以,如果没有的话会在本模型中创建该字段。 常见问题: 启动报错:根据报错内容进行相应修改 保存报错:Duplicate entry '******' for key 'PRIMARY',报这个错是因为studentName是唯一键,在将相同name的值赋值给studentName时导致唯一键冲突。其他关系也会有此情况。 O2M关系字段 配置示例: @Field(displayName = "教师关联宠物") @Field.one2many @Field.Relation(relationFields = {"id"}, referenceFields = {"teacherId"}) private List<PetShop> studentsCode; 解析: 在这个一对多关系中,id为本模型的字段,teacherId为PetShop的字段,这个一对多关系通过这两个字段关联起来。 在保存该关联关系时,会将id的值带到teacherId里并保存在PetShop模型中(many) id必须在本模型中定义(one), teacherId在PetShop模型里面定义不定义都可以,如果没有的话会在PetShop模型中创建该字段。 常见问题: 启动报错:根据报错内容进行相应修改 保存报错:请先保存关联关系模型:如果 id 为自定义字段 与 PetShop进行关联,那么保存关联关系时必须给id 赋值,不然会报错 M2M关系字段 配置示例1: @Field.many2many(through = OrderRelLogistics.MODEL_MODEL, relationFields = {"parentOrderId"}, referenceFields = {"logisticsBillId"}) @Field.Relation(relationFields = {"id"}, referenceFields = {"id"}) @Field(displayName = "物流单") private List<LogisticsBill> logisticsBillList; 解析: 在这个多对多关系中,id(左)为本模型的字段,id(右)为PetShop的字段。OrderRelLogistics.MODEL_MODEL为中间表,在保存关联关系时中间表会维护双方的关系字段,id(左)的值写到中间表的parentOrderId字段,id(右)的值写到中间表的logisticsBillId字段。 常见问题: 保存报错,请先保存关联关系模型:如果id(左)为在本模型自定义的字段,则需要在保存关联关系的时候的时候将该自定义赋值,这样才能正确保存关联关系。 配置示例2: 新增TalentTypeEnum @Dict(dictionary = TalentTypeEnum.DICTIONARY,displayName = “达人类型”) public class TalentTypeEnum extends BaseEnum { public static final String DICTIONARY =”top.TalentTypeEnum”; public final static TalentTypeEnum DOG =create(“DOG”,1,”狗达人”,”狗达人”); public final static TalentTypeEnum CAT =create(“CAT”,2,”猫达人”,”猫达人”); } 中间表定义 @Model.model(PetItemRelPetTalent.MODEL_MODEL) @Model(displayName = “中间表”, summary = “中间表”) public class PetItemRelPetTalent extends BaseRelation { public static final String MODEL_MODEL = “top.PetItemRelPetTalent”; @Field.String @Field(displayName = “商店ID”) private String petItemId; @Field.String @Field(displayName = “宠物ID”) private String petTalentId; @Field.String @Field(displayName = “宠物类型”) private TalentTypeEnum talentType; } 关系字段定义(关联关系中,使用”##“包括定义常量,这里定义常量"test") @Field(displayName = “推荐达人”) @Field.many2many( through = PetItemRelPetTalent.MODEL_MODEL, relationFields = {“petItemId”}, referenceFields = {“petTalentId”,”talentType”} ) @Field.Relation(relationFields = {“id”}, referenceFields = {“id”, “#2#”})…

    2024年8月9日
    1.4K00
  • 自定义表达式函数

    由于表达式内的函数在前后端都可能执行,所以同一个表达式需要前后端同时定义 后端表达式自定义 package pro.shushi.pamirs.demo.core.fun; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.common.constants.NamespaceConstants; import java.util.Date; import java.util.List; import static pro.shushi.pamirs.meta.enmu.FunctionCategoryEnum.TEXT; import static pro.shushi.pamirs.meta.enmu.FunctionCategoryEnum.TIME; import static pro.shushi.pamirs.meta.enmu.FunctionLanguageEnum.JAVA; import static pro.shushi.pamirs.meta.enmu.FunctionOpenEnum.LOCAL; import static pro.shushi.pamirs.meta.enmu.FunctionSceneEnum.EXPRESSION; /** * 自定义函数 */ @Fun(NamespaceConstants.expression) public class DemoCustomFunctions { @Function.Advanced( displayName = "逗号分隔字符串数组", language = JAVA, builtin = true, category = TEXT ) @Function.fun("MY_COMMA") @Function(name = "MY_COMMA", scene = {EXPRESSION}, openLevel = LOCAL, summary = "函数示例: MY_COMMA(list)\n函数说明: 将字符串数组转为逗号分隔的字符串" ) public String myComma(List<String> list) { return StringUtils.join(list, ","); } @Function.Advanced( displayName = "根据出生算年龄", language = JAVA, builtin = true, category = TIME ) @Function.fun("CALC_AGE") @Function(name = "CALC_AGE", scene = {EXPRESSION}, openLevel = LOCAL, summary = "函数示例: CALC_AGE(birthDate)\n函数说明: 根据出生算年龄" ) public Integer calcAge(Date birthDate) { if (birthDate == null) { return 0; } return new DateTime().getYear() – new DateTime(birthDate).getYear(); } } 前端表达式定义 定义后导入到main.ts里,导入@kunlun/dependencies的代码之后 import { Expression } from '@kunlun/dependencies'; import dayjs from 'dayjs'; Expression.getInstance().registerFunction('MY_COMMA', ['array'], (list: string[]) => { return (list || []) .map((value) => { return `'${value}'`; }) .join(','); }); Expression.getInstance().registerFunction('CALC_AGE', ['string'], (birthDate: string) => { if (birthDate == null) { return 0; } return Math.ceil(dayjs().year() – dayjs(birthDate,…

    2024年7月10日
    1.8K00
  • 4.7.5版本升级说明-20240204

    版本号: 4.7.5版本发布日期:2024.02.04更新要点:增强EIP流程配置扩展;补全工作流公司信息;提供Nacos为配置中心和注册中心。请及时更新。 4.7.x版本 升级内容 1、EIP增加InOutFunction函数配置; 2、工作流实例补全公司信息; 3、支持Nacos作为配置中心和注册中心; 4、登录Session支持续期; 版本包信息 4.7.0 4.7.3.3 4.7.7.5 4.7.5.3 4.7.7.5 4.7.4.1 4.7.3 4.7.0 4.7.2 4.7.6.8 4.7.3.1 4.7.0 4.7.2 4.7.1 4.7.1.1 4.7.4.1 4.7.0 4.7.1 4.7.1 设计器镜像版本 harbor.oinone.top/oinone/designer:4.7.10.9-allinone-mini 仅包含前后端工程harbor.oinone.top/oinone/designer:4.7.10.9-allinone-full 包含中间件及前后端工程harbor.oinone.top/oinone/designer-backend:latest 仅包含后端工程 其他参考 更多4.7.x的版本说明,参考:https://doc.oinone.top/version/4782.html 如果您有任何问题、建议或反馈,请随时联系我们。为了获得最佳体验,请及时更新至最新版本。我们将继续努力改进产品,提供更好的服务。谢谢!

    2024年2月4日
    1.0K00

Leave a Reply

登录后才能评论