深度分页问题优化方案

问题原因

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低代码应用平台体验

Like (0)
's avatar
Previous 2023年6月20日 pm4:07
Next 2023年11月2日 pm1:58

相关推荐

  • 翻译

    翻译应用是管理翻译规则的应用,以模型为基础、维护字段的翻译值,支持导入、导出 1. 操作步骤 Step1:导出所有翻译项; Step2:线下翻译; Step3:导入翻译项; Step4:刷新远程资源; Step5:页面右上角可切换语言,查看翻译效果。 2. 新增翻译 翻译是具体到模型字段,其中需要区分出是否字典; 源语言、目标语言,是在资源中维护的语言,可在资源中维护需要翻译的语言; 翻译项则是模型字段,默认翻译项为激活状态,关闭后维护的翻译项无效。 3. 导出、导入 不勾选导出:导出所有需要翻译的翻译项,包括模块、字段,源术语、翻译值等,其中如果已经翻译过的内容,会体现在翻译值中; 勾选导出:导出勾选模型的翻译项。 导入:导入翻译项,平台会根据模型拆分为多条数据。 4. 刷新远程资源 导入翻译项后,点击“刷新远程资源”按钮。 5. 查看翻译内容 页面右上角切换语言,查看翻译效果。

    2024年6月20日
    1.2K00
  • 上下文在字段和动作中的应用

    上下文在字段和动作中的应用 在业务场景中,常常需要在打开弹窗或跳转到新页面时携带当前页面数据。此时,我们需要配置相关「动作」中的上下文信息。 在 oinone 平台中,上下文主要分为以下三种: activeRecord:当前视图数据 rootRecord:主视图数据 openerRecord:触发弹窗的对象 参考文档:oinone内的主视图数据和当前视图数据使用介绍 activeRecord 表示当前视图的数据。例如,若动作配置在表单上,则指代当前表单的数据;若配置在 o2m、m2m 字段表格上,则指代选中的行数据。 rootRecord 表示根视图的数据。若当前视图是表单页,则代表表单的数据;若为表格页,则代表表格的数据。 openerRecord 表示触发弹窗的对象。例如,在弹窗内的字段或动作中,可通过 openerRecord 获取触发弹窗的信息。 这三者均为对象 (Object) 类型。 界面设计器配置 在 o2m、m2m 表格字段弹窗中携带当前视图数据 假设我们设计了一个包含 o2m、m2m 表格字段的表单页面。打开相关弹窗时,需将表单中的 code 数据传递至弹窗中。 选择相应的「动作」,如创建或添加。在右侧属性面板底部找到「上下文」,添加格式为对象 {} 的上下文信息。 以键值对的格式添加上下文信息:{code: rootRecord.code}。 设计弹窗时,将 code 字段拖入弹窗中。 完成设计后保存并发布。 大家可以看到,上下文中的key是 code,但是value是rootRecord.code,这里取的是rootRecord而不是activeRecord,因为我们上面讲过如果当前动作配置在o2m、m2m的字段表格上面,那么activeRecord就是表格选中的行,我们现在要取的是表单上的code字段,所以需要用rootRecord。 注意点:key需要是提交模型【前端视图】存在的字段才能传递。

    2023年11月8日
    2.9K10
  • 5.2.0版本bugfix:修复界面设计器编辑低代码菜单出现异常的问题,请升级对应版本

    版本号: 5.2.16 版本发布日期:2024.12.16更新要点:修复界面设计器编辑低代码菜单出现异常的问题 5.2.0 版本 升级说明及步骤(已升级为5.0.0版本忽略) 此版本与4.7.8版本的兼容方案如下,请严格参照升级说明及步骤进行1、【重要】升级前备份base库和用户权限模块所在的库 2、【重要】升级过程执行SQL严格按照升级文档中的步骤执行。特别注意:部分SQL是要求【发布前执行】,部分SQL是要求【发布后执行】 5.0.0升级详细说明及步骤 升级内容(5.2.0) 修复界面设计器编辑低代码菜单出现异常的问题 流程设计器触发节点选择模型时补充模型编码 修复设置首页和高级首页配置的菜单显示名称异常的问题 修复树组件在执行删除后刷新时,展开节点未正确加载的问题 请尽可能保证业务工程前后端服务以及设计器同步升级前端服务仅需重新执行npm install即可自动升级到最新版本 后端版本包信息 Oinone平台部署及依赖说明(v5.0) 未使用到的版本号请忽略,按项目中使用到的进行替换。 <!– 平台基础 –> <oinone.version>5.2.16</oinone.version> <!– 设计器 –> <pamirs.workflow.designer.version>5.2.0</pamirs.workflow.designer.version> <pamirs.model.designer.version>5.2.8</pamirs.model.designer.version> <pamirs.ui.designer.version>5.2.13</pamirs.ui.designer.version> <pamirs.data.designer.version>5.2.5</pamirs.data.designer.version> <pamirs.dataflow.designer.version>5.2.0</pamirs.dataflow.designer.version> <pamirs.eip.designer.version>5.2.6</pamirs.eip.designer.version> <dependencyManagement> <dependencies> <dependency> <groupId>pro.shushi</groupId> <artifactId>oinone-bom</artifactId> <version>${oinone.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> oinone-bom详细版本信息 <!– 平台基础 –> <pamirs.middleware.version>5.2.3</pamirs.middleware.version> <pamirs.k2.version>5.2.11</pamirs.k2.version> <pamirs.framework.version>5.2.15</pamirs.framework.version> <pamirs.boot.version>5.2.16</pamirs.boot.version> <pamirs.distribution.version>5.2.7</pamirs.distribution.version> <!– 平台功能 –> <pamirs.metadata.manager>5.2.1</pamirs.metadata.manager> <pamirs.designer.metadata.version>5.2.2</pamirs.designer.metadata.version> <pamirs.core.version>5.2.21</pamirs.core.version> <pamirs.workflow.version>5.2.7</pamirs.workflow.version> <pamirs.workbench.version>5.2.0</pamirs.workbench.version> <pamirs.data.visualization.version>5.2.7</pamirs.data.visualization.version> <!– 设计器 –> <pamirs.designer.common.version>5.2.3</pamirs.designer.common.version> <pamirs.flow.designer.base.version>5.2.5</pamirs.flow.designer.base.version> 前端版本包信息 { "@kunlun/vue-dependencies": "5.2.29", "@kunlun/vue-ui-antd": "5.2.29", "@kunlun/vue-ui-el": "5.2.29", "@kunlun/vue-mobile-dependencies": "5.2.12", "@kunlun/vue-ui-mobile-vant": "5.2.12", "@kunlun/mobile-workbench": "5.2.5", "@kunlun/data-designer-open-pc": "5.2.1", "@kunlun/data-designer-open-mobile": "5.2.1" } 前端详细版本信息 可通过node_modules/@kunlun查看 { "@kunlun/cache": "5.2.8", "@kunlun/dsl": "5.2.8", "@kunlun/event": "5.2.8", "@kunlun/expression": "5.2.8", "@kunlun/meta": "5.2.8", "@kunlun/request": "5.2.8", "@kunlun/router": "5.2.8", "@kunlun/service": "5.2.8", "@kunlun/shared": "5.2.8", "@kunlun/spi": "5.2.8", "@kunlun/state": "5.2.8", "@kunlun/theme": "5.2.8", "@kunlun/engine": "5.2.10", "@kunlun/vue-admin-base": "5.2.29", "@kunlun/vue-admin-layout": "5.2.29", "@kunlun/vue-dependencies": "5.2.29", "@kunlun/vue-router": "5.2.29", "@kunlun/vue-ui": "5.2.29", "@kunlun/vue-ui-antd": "5.2.29", "@kunlun/vue-ui-common": "5.2.29", "@kunlun/vue-ui-el": "5.2.29", "@kunlun/vue-widget": "5.2.29", "@kunlun/vue-expression": "5.2.0", "@kunlun/vue-mobile-base": "5.2.12", "@kunlun/vue-mobile-dependencies": "5.2.12", "@kunlun/vue-ui-mobile-vant": "5.2.12", "@kunlun/mobile-workbench": "5.2.5", "@kunlun/data-designer-core": "5.2.1", "@kunlun/data-designer-core-mobile": "5.2.1", "@kunlun/data-designer-core-pc": "5.2.1", "@kunlun/data-designer-open-mobile": "5.2.1", "@kunlun/data-designer-open-pc": "5.2.1" } 镜像说明 所有镜像均使用docker manifest支持amd64和arm64架构。如镜像拉取过慢,可在对应镜像Tag添加-amd64、-arm64后缀获取单一架构镜像。 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.2:5.2.16-amd64 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.2:5.2.16-arm64 镜像拉取 镜像或JAR版本:5.2.16 体验镜像:(所有中间件及前后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.2:5.2.16 部署镜像:(包含前后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/oinone-designer-mini-v5.2:5.2.16 流程设计器镜像:(包含前后端服务,仅包含流程设计器) docker pull harbor.oinone.top/oinone/workflow-designer-v5.2:5.2.16 后端镜像:(仅包含后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/designer-backend-v5.2:5.2.16…

    2024年12月16日
    1.2K00
  • 正式版发布:Oinone 6.0.0 版本 新增涡轮增压加速启动,邀您体验

    版本号: 6.0.0 版本发布日期:2025.03.17更新要点:新增涡轮增压加速启动 6.0.0 版本 启动工程关于pamirs包的扫描顺序需要进行修复 @ComponentScan( basePackages = { "pro.shushi.pamirs", } ) 20250418升级内容 镜像版本升级: 6.0.1.4 –> 6.0.2 前端版本升级 后端版本升级:6.0.1.6 –> 6.0.2 修复跨模块追加函数或模块重载时导致未启动模块元数据丢失的问题 修复登录页面语言与登录后不一致的问题 20250407升级内容 镜像版本升级: 6.0.1.3 –> 6.0.1.4 后端版本升级: 6.0.1.5 –> 6.0.1.6 修复无界面设计器环境下,标品安装元数据时因自定义组件导致的启动报错或自定义组件不生效问题 修复界面设计器部分服务无法远程调用的问题 同步更新5.7.x-20250328版本升级内容 修复在某些特殊情况下启动时,首页元数据保存错误的问题 修复界面设计器在2023年3月之前的视图无法正常发布的问题 20250326升级内容 镜像版本升级: 6.0.0.1 –> 6.0.1.3 前端版本升级 后端版本升级:6.0.1.2 –> 6.0.1.5 新增调试工具返回服务端日志的功能 修复在特殊情况下发生Class.forName死锁的问题 20250325升级内容 镜像版本升级: 6.0.0.1 –> 6.0.1.1 前端版本升级 后端版本升级:6.0.1.2 支持URL动态配置 URL动作支持计算函数 字段添加属性-字段动作配置 表格的优化。允许进行新增/复制一行等操作 表格列自动调节宽度 表单、详情动作区动作可以固定。 优化分布式持久化内存大小(内存占用约减少30%以上) 同步更新5.7.x-20250320版本升级内容 修复启动初始化Bean顺序导致空指针的问题 修复模块依赖转换错误的问题 修复跨模块继承元数据在包含jar包依赖时计算错误的问题 移除对无代码模块自动生成视图的支持 修复URL链接动作元数据无法填充compute的问题 修复工作流审批详情获取数据错误的问题 支持退回流程上文中任意人工节点 业务流程、工作流详情, 自定义审批人信息补充 修复界面设计器保存菜单时导致元数据反解析错误的问题 升级内容(6.0.0) 新增涡轮增压加速启动(启动速度约提升30%以上) 业务工程新增依赖项 <dependency> <groupId>pro.shushi.pamirs.framework</groupId> <artifactId>pamirs-framework-turbo</artifactId> </dependency> 请尽可能保证业务工程前后端服务以及设计器同步升级前端服务仅需重新执行npm run clean && npm install即可自动升级到最新版本 后端版本包信息 Oinone平台部署及依赖说明(v5.3) 未使用到的版本号请忽略,按项目中使用到的进行替换。 <!– 平台基础 –> <oinone.version>6.0.2</oinone.version> <!– 设计器 –> <pamirs.workflow.designer.version>6.0.0</pamirs.workflow.designer.version> <pamirs.model.designer.version>6.0.1</pamirs.model.designer.version> <pamirs.ui.designer.version>6.0.2</pamirs.ui.designer.version> <pamirs.print.designer.version>6.0.0</pamirs.print.designer.version> <pamirs.data.designer.version>6.0.1</pamirs.data.designer.version> <pamirs.dataflow.designer.version>6.0.0</pamirs.dataflow.designer.version> <pamirs.eip.designer.version>6.0.2</pamirs.eip.designer.version> <pamirs.microflow.designer.version>6.0.0</pamirs.microflow.designer.version> <dependencyManagement> <dependencies> <dependency> <groupId>pro.shushi</groupId> <artifactId>oinone-bom</artifactId> <version>${oinone.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> oinone-bom详细版本信息 <!– 平台基础 –> <pamirs.middleware.version>6.0.0</pamirs.middleware.version> <pamirs.k2.version>6.0.4</pamirs.k2.version> <pamirs.framework.version>6.0.8</pamirs.framework.version> <pamirs.boot.version>6.0.6</pamirs.boot.version> <pamirs.distribution.version>6.0.4</pamirs.distribution.version> <!– 平台功能 –> <pamirs.metadata.manager>6.0.0</pamirs.metadata.manager> <pamirs.designer.metadata.version>6.0.1</pamirs.designer.metadata.version> <pamirs.core.version>6.0.7</pamirs.core.version> <pamirs.workflow.version>6.0.3</pamirs.workflow.version> <pamirs.workbench.version>6.0.1</pamirs.workbench.version> <pamirs.data.visualization.version>6.0.1</pamirs.data.visualization.version> <!– 设计器 –> <pamirs.designer.common.version>6.0.1</pamirs.designer.common.version> <pamirs.flow.designer.base.version>6.0.2</pamirs.flow.designer.base.version> 前端版本包信息 { "@kunlun/dependencies": "6.0.3", "@kunlun/vue-ui-antd": "6.0.3", "@kunlun/vue-ui-el": "6.0.3", "@kunlun/mobile-dependencies": "6.0.0", "@kunlun/vue-ui-mobile-vant": "6.0.0", "@kunlun/mobile-workbench": "6.0.0", "@kunlun/data-designer-open-pc": "6.0.0", "@kunlun/data-designer-open-mobile": "6.0.0" } 前端详细版本信息 可通过node_modules/@kunlun查看 { "@kunlun/cache": "6.0.0", "@kunlun/dsl": "6.0.0", "@kunlun/environment": "6.0.0", "@kunlun/event": "6.0.0", "@kunlun/expression": "6.0.0", "@kunlun/meta": "6.0.0", "@kunlun/request": "6.0.0", "@kunlun/router": "6.0.0", "@kunlun/service": "6.0.0", "@kunlun/shared":…

    2025年3月17日
    1.1K00
  • mybatis拦截器的使用

    场景:自定义拦截器做数据的加解密。 注册自定义拦截器 @Configuration public class MyBatisConfig { // TODO: 注册自定义拦截器 @Bean @Order(999) public EncryptionInterceptor encryptionInterceptor() { return new EncryptionInterceptor(); } } 使用mybatis拦截器拦截查询。 @Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class EncryptionInterceptor implements Interceptor { @Autowired private EncryptionConfig encryptionConfig; @Override public Object intercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); MappedStatement ms = (MappedStatement) args[0]; Object parameter = args[1]; // 判断操作类型是insert, update 或 delete if (ms.getSqlCommandType().equals(SqlCommandType.INSERT) || ms.getSqlCommandType().equals(SqlCommandType.UPDATE) || ms.getSqlCommandType().equals(SqlCommandType.DELETE)) { // TODO: 加密字段 encryptFields(parameter); } else if (ms.getSqlCommandType().equals(SqlCommandType.SELECT)) { // TODO: 查询操作,在执行后需要对结果进行解密 Object result = invocation.proceed(); List<EncryptionConfig.Models> models = encryptionConfig.getModels(); for (EncryptionConfig.Models model : models) { if (judgmentModel(parameter, model)) { decryptFields(result); } } return result; } return invocation.proceed(); } private Boolean judgmentModel(Object parameter, EncryptionConfig.Models model) { MetaObject metaObject = SystemMetaObject.forObject(parameter); if (metaObject.getOriginalObject() instanceof MapperMethod.ParamMap) { if (metaObject.hasGetter("ew")) { Object param1 = metaObject.getValue("ew"); if (param1 != null) { Object originalObject = SystemMetaObject.forObject(param1).getOriginalObject(); if (originalObject instanceof QueryWrapper) { DataMap entity = (DataMap) ((QueryWrapper<?>) originalObject).getEntity(); if (entity != null) { Object modelFieldName = entity.get(FieldConstants._d_modelFieldName);…

    2024年12月2日
    1.5K00

Leave a Reply

Please Login to Comment