深度分页问题优化方案

问题原因

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.5 Oinone与行业对比

    随着企业数字化转型的推进,软件公司获得了许多机会。尽管竞争日趋激烈,但由于需求旺盛,各种模式仍在不断涌现。因此,当前市场上存在各种各样的数字化转型解决方案,围绕企业的各个方面展开。每种解决方案都有其优点和缺点。本文将从定位、技术和产品等方面简单比较,帮助您从不同的视角了解Oinone的差异。 1.4.1 整体视角对比 一、与对标公司Odoo的对比 Odoo Oinone 定位 一站式全业务链管理平台:赋能企业信息化升级 一站式低代码商业支撑平台:赋能企业数字化升级 需求变化 关注单一企业的管理、流程、效率的提升 关注企业价值链的网络竞争,围绕外部协同、运营、数据、商业展开 技术更替 关注稳定、安全、功能丰富度 除了稳定、安全、功能丰富度以外,更强调需求响应速度、用户体验、系统承载极限与弹性扩展、智能化 表1-1 Oinone与对标公司Odoo的对比 二、与国内低代码或无代码公司对比 低代码或无代码公司 Oinone 定位 低代码开发工具:提供各类系统模版,基于模版快速搭建和个性化配置。但系统模版无法再升级 平台型SaaS:提供各类系统产品,产品安装后客户可以根据需求进行个性化调整,同时产品永远在线可升级 场景差异 只能支持企业内部人员使用,以完成部门级边缘系统为主,一般多为没有专业软件厂商支撑和强临时性特性 从内外部协同的商业场景出发,关注企业核心业务场景,适应【企业业务在线化后,所有的业务变化与创新都需要通过系统来触达上下游】的时代背景,以敏捷响应业务的变化与创新为目标 技术代差 单表支撑100万数据已是业内天花板 支撑单模型数据过亿,无单点瓶颈。封装互联网架构并且做到单体与分布式的灵活部署,为不同大小公司提供不同技术支撑 表1-2 Oinone与国内低代码/无代码公司对比 1.4.2 从技术角度对比 我们不会与其他无代码平台进行比较,因为它们不能解决业务复杂性的问题。相反,我们将重点介绍三种不同的低代码平台模式(如下图1-8所示)。 第一种模式是最基础的低代码平台,也被称为代码生成器。它通过预定义应用程序模板和必要的配置生成代码,简化了工程搭建并提供了一些基础逻辑。虽然在信息化时代内部流程标准化方面较为适合,但在数字化时代外部协同业务在线的情况下就不那么合适了。因为这种模式不能减少研发难度和提高效率,也无法体现敏捷迭代快速创新的优势。 第二种模式是经典的低代码平台,以元数据为基础,以模型为驱动。当无法满足需要时,通过特定方式将代码以插件的形式注入平台,作为低代码平台的内置逻辑,供设计器使用。它的优点在于降低了研发门槛,当无法满足需求时才需要编写代码。它可以实现企业内部的复杂流程和复杂逻辑,但其性能和工程管理存在局限性。性能问题使其不适合处理互联网化的在线业务,而工程管理问题则使其不适合处理快速变化的业务。这也是许多研发人员反对低代码的核心原因之一,因为研发人员变成了辅助角色,而软件工程是一门需要技术能力的学科,让没有技术能力的人主导是违反常理的。对于软件产品公司来说,产品需要迭代规划,需要多人协作,需要工程化管理。 第三种模式是oinone提出的基于互联网架构的低代码平台,它采用低无一体的设计。首先,oinone屏蔽了互联网架构带来的复杂性。其次,同样以元数据为基础,以模型为驱动,但是元数据的生成方式有两种:一种是使用无代码设计器(与经典低代码相同),另一种是通过代码来描述元数据。通过使用代码来描述元数据,可以无缝地与代码衔接,并在不改变研发习惯的情况下降低门槛、提高效率,并进行工程化管理。 最后总结来说:低无一体不仅仅是指两种模式的结合,还包括两种模式的融合应用方式。具体来说,这种融合应用方式可以分为两种情况: 当开发核心产品时,主要采用低代码开发,无代码设计器作为辅助。这种方式可以提高开发效率和代码质量,同时保证产品的快速迭代和升级。 当需要满足个性化或非产品支持的需求时,主要采用无代码设计器,低代码作为辅助。这种方式可以快速地满足客户需求,并且避免对产品的核心代码产生影响。 简单来说,低代码模式适用于产品的迭代升级,而无代码设计器则适用于满足个性化和非产品支撑的额外需求。低代码和无代码模式在整个软件生命周期中都有各自的价值,在不同场景下可以相互融合,发挥最大的优势。 图1-8 代码生成器、低代码平台与Oinone的优缺点对比 1.4.3 从产品角度对比 产品上的对比,从客户、场景满足度、再次销售三个方面来做简易的对比 一、Oinone vs 数字化软件服务商 客户 满足度 销售 Oinone 一站式商业智能软件,更高性价比、用户体验客户范围:5000万~5亿、5亿~100亿、标杆:100亿~1000亿、1000亿以上 满足企业核心业务需求,并联合伙伴一起满足企业所有需求,无需集成提供统一工作台、数据接口、底层协议,无论基于Oinone的开源框架还是增加其他应用都有很好的扩展性 支持OP+SaaS两种模式,收费方式不同:OP按买断方式进行,SaaS按效果付费跟账号数无关新的模块进行二次销售 数字化软件服务商 针对成熟的大型企业需投入巨大资源和成本客户范围:100亿~1000亿、1000亿以上 满足企业部分需求,无法输出技术标准,无法解决多供应商一起开发的问题,只能通过集成实现对接 OP模式进行销售,通过设置权限来进行来实现二次销售或无法进行二次销售 表1-3 Oinone vs 数字化软件服务商 二、Oinone vs 低代码或无代码行业 客户 满足度 销售 Oinone 一站式商业智能软件客户范围:5000万~5亿、5亿~100亿、标杆:100亿~1000亿、1000亿以上 从外部商业场景出发,强业务场景驱动,符合企业从信息化管理到业务创新的数字化转变的趋势。提供统一工作台、数据接口、底层协议,无论基于oinone的开源框架还是增加其他应用都有很好的扩展性 支持OP+SaaS两种模式,收费方式不同:OP按买断方式进行,SaaS按效果付费跟账号数无关新的模块进行二次销售 低代码或无代码公司 针对小微企业内部信息化管理诉求,以表单流程为主客户范围:5亿以下 满足企业部门级信息化的适应性需求,无法满足企业核心业务管理与业务创新诉求 按应用模块进行收费,新的模块进行二次销售 表1-4 Oinone vs 低代码或无代码行业 三、Oinone vs 国外对标公司Odoo 客户 满足度 销售 Oinone 一站式商业智能软件客户范围:5000万~5亿、5亿~100亿、标杆:100亿~1000亿、1000亿以上 从外部商业场景出发,强业务场景驱动,符合企业从信息化管理到业务创新的数字化转变的趋势。基线产品覆盖:采购、营销、服务、销售、交易等企业商业领域。主要涉及行业:零售品牌。其他领域或行业靠合作伙伴共建方式进行 支持OP+SaaS两种模式,收费方式不同:OP按买断方式进行,SaaS按效果付费跟账号数无关新的模块进行二次销售 Odoo 一站式企业管理软件客户范围:5000万~5亿、5亿~100亿、标杆:100亿~1000亿、1000亿以上 从企业内部管理需求出发,逐渐拥有互联网相关应用组件,但还是属于强内部管理、弱外部场景。基线产品覆盖:业务财务一体化、人财务、进销存。主要涉及行业:建造业。其他领域或行业靠合作伙伴共建方式进行 支持OP+SaaS两种模式,收费方式相同:按用户数+应用模块进行收费新的模块进行二次销售 表1-5 Oinone vs 国外对标公司Odoo

    2024年5月23日
    2.0K20
  • 界面设计器的导入导出

    目录 依赖包安装GraphQL的工具登录gql导出生成json文件子业务工程中导入示例代码 简介 通过调用导出接口,将设计器的设计数据与元数据打包导出到文件中。提供了download/export两类接口。 依赖包 <dependency> <groupId>pro.shushi.pamirs.metadata.manager</groupId> <artifactId>pamirs-metadata-manager</artifactId> </dependency> 安装GraphQL的工具 下载官网地址:https://github.com/Kong/insomnia/releases 登录gql 示例调用代码 mutation { pamirsUserTransientMutation { login(user: { login: "admin", password: "admin" }) { needRedirect broken errorMsg errorCode errorField } } } 导出生成json文件 执行GraphQL,直接返回导出数据。适用于通过浏览器直接下载文件。 按模块示例调用代码 请求示例: mutation { uiDesignerExportReqMutation { download/export( data: { module: "demo_core", fileName: "demo_meta", moduleBasics: false } ) { jsonUrl } } } module参数:模块编码; fileName参数:指定⽣成的json⽂件名称; moduleBasics参数:指定是否只导出模块基础数据,如果为true,只导出内置布局、模块菜单、菜单关联的动作。 如果为false,还会导出模块内的所有页⾯,以及页⾯关联的动作元数据、页⾯设计数据 等等。 默认值为false。 按菜单导出 mutation { uiDesignerExportReqMutation { download/export( data: { menu: { name: "uiMenu0000000000048001" } fileName: "demo_meta" relationViews: true } ) { jsonUrl } } } menu参数:菜单对象,指定菜单的name。只会导出该菜单及其绑定页⾯,不会递归查询⼦菜单 fileName参数:指定⽣成的json⽂件名称 relationViews参数:指定是否导出关联页⾯,默认为false,只导出菜单关联的页⾯。如果为true,还会导出该页⾯通过跳转动作关联的⾃定义页⾯。 指定页⾯导出 mutation { uiDesignerExportReqMutation { download/export( data: { view: { name: "xx_TABLE_0000000000119001" model: "ui.designer.TestUiDesigner" } fileName: "demo_meta" relationViews: true } ) { jsonUrl } } } view参数:视图对象,指定视图的name和model fileName参数:指定⽣成的json⽂件名称 relationViews参数:指定是否导出关联页⾯,默认为false,只导出菜单关联的页⾯。如果为true,还会导出该页⾯通过跳转动作关联的⾃定义页⾯。 导出组件 导出全部组件数据 mutation { uiDesignerExportReqMutation { downloadWidget/exportWidget(data: { fileName: "demo_widget" }) { jsonUrl } } } fileName参数:指定⽣成的json⽂件名称 注意:⾃定义组件的元数据归属于页⾯设计器(ui_designer) 因此导⼊元数据的模块(module)并不是业务模块。组件导⼊建议使⽤pro.shushi.pamirs.metadata.manager.core.helper.WidgetInstallHelper 导出全部组件⽂件 当开发环境,和导⼊环境的oss不互通时,可通过⼀下⽅法导出⾃定义组件的css和js⽂件压缩包,在导⼊时⽀持指定zip⽂件上传到oss,并替换导⼊组件数据中的css和js⽂件路径。 mutation { uiDesignerExportReqMutation { downloadWidgetFile/exportWidgetFile(data: { fileName: "demo_widget" }) { jsonUrl } } } 业务工程中导入示例代码 导入元数据示例代码(运行时数据) @Slf4j @Order(Integer.MAX_VALUE-1) @Component public class DemoAppMetaInstall implements MetaDataEditor { @Autowired private ApplicationContext applicationContext; @Override public void edit(AppLifecycleCommand command, Map<String, Meta> metaMap) { if (!doImport())…

    2024年5月16日
    2.0K00
  • 自定义表达式函数

    由于表达式内的函数在前后端都可能执行,所以同一个表达式需要前后端同时定义 后端表达式自定义 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日
    2.0K00
  • 序列化工具使用问题

    后端使用的JSON序列化JsonUtils.toJSONString(nodes);前端使用的JSON序列化PamirsJsonUtils.toJSONString(nodes, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.BrowserCompatible);注意:用什么工具序列化,就用什么工具反序列化、parse 的时候,要保持一致, 使用PamirsJsonUtils序列化工具主要是为了解决枚举取值错误的问题以及id精度丢失问题。当出现这两个问题的时候,需要使用PamirsJsonUtils 进行序列化。

    2024年9月5日
    1.4K00
  • 5.0.4版本bugfix:修复Schedule远程调用的问题,请升级对应版本

    版本号: 5.0.20 版本发布日期:2024.08.27更新要点: 修复Schedule远程调用的问题 5.0.20 版本 升级说明及步骤(已升级为5.0.0版本忽略) 此版本与4.7.8版本的兼容方案如下,请严格参照升级说明及步骤进行1、【重要】升级前备份base库和用户权限模块所在的库 2、【重要】升级过程执行SQL严格按照升级文档中的步骤执行。特别注意:部分SQL是要求【发布前执行】,部分SQL是要求【发布后执行】 5.0.0升级详细说明及步骤 升级内容(5.0.0) 修复Schedule远程调用的问题 修复数据可视化未正确查询图表模板的问题 修复界面设计器在使用pgsql时删除菜单报错的问题 请尽可能保证业务工程前后端服务以及设计器同步升级前端服务仅需重新执行npm install即可自动升级到最新版本 版本包信息 Oinone平台部署及依赖说明(v5.0) 未使用到的版本号请忽略,按项目中使用到的进行替换。 <!– 平台基础 –> <pamirs.middleware.version>5.0.3</pamirs.middleware.version> <pamirs.k2.version>5.0.10</pamirs.k2.version> <pamirs.framework.version>5.0.29</pamirs.framework.version> <pamirs.boot.version>5.0.21</pamirs.boot.version> <pamirs.distribution.version>5.0.11</pamirs.distribution.version> <!– 平台功能 –> <pamirs.metadata.manager>5.0.1</pamirs.metadata.manager> <pamirs.core.version>5.0.42</pamirs.core.version> <pamirs.workflow.version>5.0.11</pamirs.workflow.version> <pamirs.workbench.version>5.0.3</pamirs.workbench.version> <pamirs.data.visualization.version>5.0.4</pamirs.data.visualization.version> <!– 设计器 –> <pamirs.designer.common.version>5.0.5</pamirs.designer.common.version> <pamirs.flow.designer.base.version>5.0.3</pamirs.flow.designer.base.version> <pamirs.workflow.designer.version>5.0.2</pamirs.workflow.designer.version> <pamirs.model.designer.version>5.0.2</pamirs.model.designer.version> <pamirs.ui.designer.version>5.0.17</pamirs.ui.designer.version> <pamirs.data.designer.version>5.0.2</pamirs.data.designer.version> <pamirs.dataflow.designer.version>5.0.3</pamirs.dataflow.designer.version> <pamirs.eip.designer.version>5.0.4</pamirs.eip.designer.version> 注意镜像名称变化 镜像说明 所有镜像均使用docker manifest支持amd64和arm64架构。如镜像拉取过慢,可在对应镜像Tag添加-amd64、-arm64后缀获取单一架构镜像。 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.0:5.0.20-amd64 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.0:5.0.20-arm64 镜像拉取 镜像或JAR版本:5.0.20 体验镜像:(所有中间件及前后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.0:5.0.20 部署镜像:(包含前后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/oinone-designer-mini-v5.0:5.0.20 流程设计器镜像:(包含前后端服务,仅包含流程设计器) PS:原workflow-designer-standard-v5.0镜像不再提供,请更换为该镜像。 docker pull harbor.oinone.top/oinone/workflow-designer-v5.0:5.0.20 后端镜像:(仅包含后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/designer-backend-v5.0:5.0.20 前端镜像:(仅包含前端服务,包含全部设计器) PS:前端镜像版本为独立版本,与其他镜像版本不同。原基础镜像为nginx-1.21.0版本,从5.0.8版本开始使用nginx-1.24.0版为基础镜像 docker pull harbor.oinone.top/oinone/designer-frontend-v5.0:5.0.31 独立部署所有设计器JAR:(后端服务,包含所有设计器)pamirs-designer-boot-v5.0-5.0.20.jarpamirs-designer-boot-v5.0-latest.jar 独立部署流程设计器JAR:(后端服务,仅包含流程设计器)pamirs-workflow-designer-boot-v5.0-5.0.20.jarpamirs-workflow-designer-boot-v5.0-latest.jar 后端无代码设计器Jar包启动方法 如果您有任何问题、建议或反馈,请随时联系我们。为了获得最佳体验,请及时更新至最新版本。我们将继续努力改进产品,提供更好的服务。谢谢!

    2024年8月27日
    1.2K00

Leave a Reply

登录后才能评论