深度分页问题优化方案

问题原因

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

相关推荐

  • 如何替换页面中的静态资源为私有存储

    介绍 为了让我们可以快速体验到oinone的产品,oinone的工程内默认提供了一个阿里云oss的存储空间来存放一些静态资源,如网站在浏览器标签栏的图标、登录页的logo、站内页面的logo、默认头像、背景图等,但是在实际业务中我们需要把其中部分静态资源更换为自有品牌或者客户品牌定制的静态资源。 解决方案 oinone提供了一套可以替换掉默认静态资源的方案 获取静态资源文件的压缩包static.zip 解压到到运维指定的目录下,这里以/project/static为例,前端通过浏览器开发工具查看到需要替换的图片路径,在static目录下找到对应路径的文件,替换为自有文件 配置nginx的文件系统(使用阿里云oss、minio等云存储方案的可以忽略该步骤) server { listen 8899; location /static { alias /project/static; add_header Content-Disposition attachment; add_header Content-Type application/octet-stream; } } 前端启动工程中的.env文件中增加如下配置(ss-boot) STATIC_IMG=http://访问地址/static/images 生产模式重新打包 或 开发模式重新运行就可以看到效果

    2024年3月20日
    2.0K00
  • 5.3.0版本feature:界面设计器新增动作快捷键设置,请升级对应版本

    版本号: 5.3.2 版本发布日期:2024.12.16更新要点:界面设计器新增动作快捷键设置 5.3.0 版本 升级说明及步骤(已升级为5.0.0版本忽略) 5.3.x版本以后无法通过4.7.8版本进行升级,请先升级到5.2.x版本进行权限迁移后再升级至5.3.x版本 升级内容(5.3.0) 界面设计器新增动作快捷键设置 工作流抄送的待办增加已读操作 工作流审批同意或者拒绝时抄送 修复界面设计器编辑低代码菜单出现异常的问题 流程设计器触发节点选择模型时补充模型编码 增加一对多类型的文件和图片组件 修复设置首页和高级首页配置的菜单显示名称异常的问题 修复树组件在执行删除后刷新时,展开节点未正确加载的问题 请尽可能保证业务工程前后端服务以及设计器同步升级前端服务仅需重新执行npm run clean && npm install即可自动升级到最新版本 后端版本包信息 Oinone平台部署及依赖说明(v5.1) 未使用到的版本号请忽略,按项目中使用到的进行替换。 <!– 平台基础 –> <oinone.version>5.3.2</oinone.version> <!– 设计器 –> <pamirs.workflow.designer.version>5.3.0</pamirs.workflow.designer.version> <pamirs.model.designer.version>5.3.1</pamirs.model.designer.version> <pamirs.ui.designer.version>5.3.2</pamirs.ui.designer.version> <pamirs.data.designer.version>5.3.0</pamirs.data.designer.version> <pamirs.dataflow.designer.version>5.3.0</pamirs.dataflow.designer.version> <pamirs.eip.designer.version>5.3.0</pamirs.eip.designer.version> <pamirs.microflow.designer.version>5.3.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>5.2.3</pamirs.middleware.version> <pamirs.k2.version>5.3.0</pamirs.k2.version> <pamirs.framework.version>5.3.0</pamirs.framework.version> <pamirs.boot.version>5.3.2</pamirs.boot.version> <pamirs.distribution.version>5.3.0</pamirs.distribution.version> <!– 平台功能 –> <pamirs.metadata.manager>5.3.0</pamirs.metadata.manager> <pamirs.designer.metadata.version>5.3.0</pamirs.designer.metadata.version> <pamirs.core.version>5.3.3</pamirs.core.version> <pamirs.workflow.version>5.3.1</pamirs.workflow.version> <pamirs.workbench.version>5.3.0</pamirs.workbench.version> <pamirs.data.visualization.version>5.3.0</pamirs.data.visualization.version> <!– 设计器 –> <pamirs.designer.common.version>5.3.0</pamirs.designer.common.version> <pamirs.flow.designer.base.version>5.3.2</pamirs.flow.designer.base.version> 前端版本包信息 { "@kunlun/vue-dependencies": "5.3.3", "@kunlun/vue-ui-antd": "5.3.3", "@kunlun/vue-ui-el": "5.3.3", "@kunlun/vue-mobile-dependencies": "5.3.1", "@kunlun/vue-ui-mobile-vant": "5.3.1", "@kunlun/mobile-workbench": "5.3.1", "@kunlun/data-designer-open-pc": "5.3.0", "@kunlun/data-designer-open-mobile": "5.3.0" } 前端详细版本信息 可通过node_modules/@kunlun查看 { "@kunlun/cache": "5.3.2", "@kunlun/dsl": "5.3.2", "@kunlun/environment": "5.3.2", "@kunlun/event": "5.3.2", "@kunlun/expression": "5.3.2", "@kunlun/meta": "5.3.2", "@kunlun/request": "5.3.2", "@kunlun/router": "5.3.2", "@kunlun/service": "5.3.2", "@kunlun/shared": "5.3.2", "@kunlun/spi": "5.3.2", "@kunlun/state": "5.3.2", "@kunlun/theme": "5.3.2", "@kunlun/engine": "5.3.2", "@kunlun/vue-admin-base": "5.3.3", "@kunlun/vue-admin-layout": "5.3.3", "@kunlun/vue-dependencies": "5.3.3", "@kunlun/vue-router": "5.3.3", "@kunlun/vue-ui": "5.3.3", "@kunlun/vue-ui-antd": "5.3.3", "@kunlun/vue-ui-common": "5.3.3", "@kunlun/vue-ui-el": "5.3.3", "@kunlun/vue-widget": "5.3.3", "@kunlun/vue-expression": "5.2.0", "@kunlun/vue-mobile-base": "5.3.1", "@kunlun/vue-mobile-dependencies": "5.3.1", "@kunlun/vue-ui-mobile-vant": "5.3.1", "@kunlun/mobile-workbench": "5.3.1", "@kunlun/data-designer-core": "5.3.0", "@kunlun/data-designer-core-mobile": "5.3.0", "@kunlun/data-designer-core-pc": "5.3.0", "@kunlun/data-designer-open-mobile": "5.3.0", "@kunlun/data-designer-open-pc": "5.3.0" } 镜像说明 所有镜像均使用docker manifest支持amd64和arm64架构。如镜像拉取过慢,可在对应镜像Tag添加-amd64、-arm64后缀获取单一架构镜像。 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.3:5.3.2.1-amd64 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.3:5.3.2.1-arm64 镜像拉取 镜像或JAR版本:5.3.2.1 体验镜像:(所有中间件及前后端服务,包含全部设计器) docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.3:5.3.2.1 部署镜像:(包含前后端服务,包含全部设计器) docker pull…

    2024年12月16日
    1.6K00
  • 4.1.19 框架之网关协议-后端占位符

    在我们日常开发中会有碰到一些特殊场景,需要由前端来传一些如“当前用户Id”、“当前用户code”诸如此类只有后端才知道值的参数,那么后端占位符就是来解决类似问题的。如前端传${currentUserId},后端会自动替换为当前用户Id。 Step1 后端定义占位符 我们新建一个UserPlaceHolder继承AbstractPlaceHolderParser,用namespace来定义一个“currentUserId”的占位符,其对应值由value()决定为“PamirsSession.getUserId().toString()”,active要为真才有效,priority为优先级 package pro.shushi.pamirs.demo.core.placeholder; import org.springframework.stereotype.Component; import pro.shushi.pamirs.meta.api.session.PamirsSession; import pro.shushi.pamirs.user.api.AbstractPlaceHolderParser; @Component public class UserPlaceHolder extends AbstractPlaceHolderParser { @Override protected String value() { return PamirsSession.getUserId().toString(); } @Override public Integer priority() { return 10; } @Override public Boolean active() { return Boolean.TRUE; } @Override public String namespace() { return "currentUserId"; } } 图4-1-19-1 后端定义占位符 Step2 前端使用后端占位符 我们经常在o2m和m2m中会设置domain来过滤数据,这里案例就是在field中设置来过滤条件,domain="createUid == $#{currentUserId}",注意这里用的是$#{currentUserId} 而不是${currentUserId},这是前端为了区分真正变量和后端占位符,提交的时候会把#过滤掉提交。修改宠物达人表格视图的Template中search部分 <template slot="search" cols="4"> <field data="name" label="达人"/> <field data="petTalentSex" multi="true" label="达人性别"/> <field data="creater" /> <!– <field data="petShops" label="宠物商店" domain="createUid == ${activeRecord.creater.id}"/>–> <field data="petShops" label="宠物商店" domain="createUid == $#{currentUserId}"/> <field data="dataStatus" label="数据状态" multi="true"> <options> <option name="DRAFT" displayName="草稿" value="DRAFT" state="ACTIVE"/> <option name="NOT_ENABLED" displayName="未启用" value="NOT_ENABLED" state="ACTIVE"/> <option name="ENABLED" displayName="已启用" value="ENABLED" state="ACTIVE"/> <option name="DISABLED" displayName="已禁用" value="DISABLED" state="ACTIVE"/> </options> </field> <field data="createDate" label="创建时间"/> <field data="unStore" /> </template> 图4-1-19-2 前端使用后端占位符 Step3 重启看效果 请求上都带上了createUid==${currentUserId} 图4-1-19-3 示例效果

    2024年5月23日
    2.5K00
  • 5.3 基础支撑之用户与客户域

    一、三户概念 三户由来 介绍下经典的三户模型,它是电信运营支持系统的基础。三户模型即客户、用户和帐户,来源于etom的模型。这三者之间的关系应该是一个相互关联但又是独立的三个实体,这种关联只是一个归属和映射的关系,而三个实体本身是相互独立的,分别是体现完全不同的几个域的信息,客户是体现了社会域的信息,用户体现了业务域的信息,帐户体现的是资金域的信息。 客户:它是个社会化的概念,一个自然人或一个法人 用户:它是客户使用运营商开发的一个产品以及基于该产品之上的增值业务时,产生的一个实体。如果说一个客户使用了多个产品,那么一个客户就会对应好几个用户(即产品) 账户:它的概念起源于金融业,只是一个客户在运营商存放资金的实体,目的是为选择的产品付费 Oinone的三户 在原三户模型中【用户】是购买关系产生的产品与客户关系的服务实例,在互联网发展中用户的概念发生了非常大的变化,【用户】概念变成了:使用者,是指使用电脑或网络服务的人,通常拥有一个用户账号,并以用户名识别。而且新概念在互联网强调用户数的大背景下已经被普遍介绍,再去强调电信行业的用户概念就会吃力不讨好。而且不管是企业应用领域和互联网领域,原用户概念都显得过于复杂和没有必要。也就有了特色的oinone的三户模型: 客户:它是个社会化的概念,一个自然人或一个法人 用户:使用者,是指使用电脑或网络服务的人,通常拥有一个用户账号,并以用户名识别 账户:它的概念起源于金融业,只是一个客户在运营商存放资金的实体,目的是为选择的产品付费 二、Oinone的客户与用户 三户模型是构建上层应用的基础支撑能力,任何业务行为都跟这里两个实体脱不了干系。以客户为中心建立商业关系与商业行为主体,以用户为中心构建一致体验与操作行为主体。在底层设计上二者相互独立并无关联,由上层应用自行作关联绑定,往往在登陆时在Session的处理逻辑中会根据【用户】去找到对应一个或多个【商业(主体)客户】,Session的实现可以参考4.1.20【框架之Session】一文。 图5-3-1 Oinone的客户与用户 客户设计说明 PamirsPartner作为商业关系与商业行为的主体,派生了两个子类PamirsCompany与PamirsPerson分别对应:公司(法人)客户、自然人客户 公司(法人)客户PamirsCompany对应多个组织部门PamirsDepartment,公司(法人)客户PamirsCompany对应多个员工PamirsEmployee 部门PamirsDepartment对应一个公司(法人)客户PamirsCompany,对应多个员工PamirsEmployee 员工PamirsEmployee对应多个部门PamirsDepartment,对应一个或多个公司(法人)客户PamirsCompany,其中有一个主的 用户设计说明 PamirsUser作为一致体验与操作行为主体,本身绑定登陆账号,并且可以关联多个三方登陆账户PamirsUserThirdParty 客户与用户如何关联(举例) 例子设计: 新建demo系统的PetComany和PetEmployee,用PetEmployee去关联用户。 当用户登陆时,根据用户Id找到PetEmployee,在根据PetEmployee找到PetComany,把PetComany放到Session中去 修改PetShop模型关联一个PamirsPartner,PamirsPartner的信息从Session取。 Step1 pamirs-demo-api工程增加依赖,并且DemoModule增加对BusinessModule的依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-business-api</artifactId> </dependency> 图5-3-2 pamirs-demo-api工程增加依赖 在DemoModule类中通过@Module.dependencies中增加BusinessModule.MODULE_MODULE @Module( dependencies = { BusinessModule.MODULE_MODULE} ) 图5-3-3 声明对BusinessModule的依赖 Step2 新建PetComany和PetEmployee,以及对应的服务 package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.business.api.model.PamirsEmployee; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; import pro.shushi.pamirs.user.api.model.PamirsUser; @Model.model(PetEmployee.MODEL_MODEL) @Model(displayName = "宠物公司员工",labelFields = "name") public class PetEmployee extends PamirsEmployee { public static final String MODEL_MODEL="demo.PetEmployee"; @Field(displayName = "用户") private PamirsUser user; } 图5-3-4 新建PetEmployee package pro.shushi.pamirs.demo.api.model; import pro.shushi.pamirs.business.api.entity.PamirsCompany; import pro.shushi.pamirs.meta.annotation.Field; import pro.shushi.pamirs.meta.annotation.Model; @Model.model(PetCompany.MODEL_MODEL) @Model(displayName = "宠物公司",labelFields = "name") public class PetCompany extends PamirsCompany { public static final String MODEL_MODEL="demo.PetCompany"; @Field.Text @Field(displayName = "简介") private String introductoin; } 图5-3-5 新建PetComany package pro.shushi.pamirs.demo.api.service; import pro.shushi.pamirs.demo.api.model.PetEmployee; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; @Fun(PetEmployeeQueryService.FUN_NAMESPACE) public interface PetEmployeeQueryService { String FUN_NAMESPACE ="demo.PetEmployeeQueryService"; @Function PetEmployee queryByUserId(Long userId); } 图5-3-6 新建PetEmployee对应服务 package pro.shushi.pamirs.demo.core.service; import org.springframework.stereotype.Component; import pro.shushi.pamirs.demo.api.model.PetEmployee; import pro.shushi.pamirs.demo.api.service.PetEmployeeQueryService; import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; @Fun(PetEmployeeQueryService.FUN_NAMESPACE) @Component public class PetEmployeeQueryServiceImpl implements PetEmployeeQueryService { @Override @Function public PetEmployee queryByUserId(Long userId) { if(userId==null){ return null; } QueryWrapper<PetEmployee> queryWrapper = new QueryWrapper<PetEmployee>().from(PetEmployee.MODEL_MODEL).eq("user_id", userId); return…

    2024年5月23日
    1.9K00
  • 早鸟版发布:Oinone 7.0.0 版本 升级 JDK17,优化全平台界面交互,邀您体验

    版本号: 7.0.0 版本发布日期:2025.12更新要点:升级 JDK17,优化全平台界面交互 7.0.0 版本 GitHub: 后端: https://github.com/oinone/oinone-pamirs 前端: https://github.com/oinone/oinone-kunlun Gitee: 后端: https://gitee.com/oinone/oinone-pamirs 前端: https://gitee.com/oinone/oinone-kunlun 升级说明及步骤 此版本升级时需要完整回归已有系统的已有功能,否则无法保证功能的正常使用。尤其是 javax -> jakarta 的变更会出现编译正常但无法正常运行的情况。 7.0.0升级详细说明及步骤 20260721 升级内容 镜像版本升级: 7.0.7 –> 7.0.8 后端版本升级: 7.0.7 –> 7.0.8 修复工作流发布时视图重复生成的问题 20260720 升级内容 镜像版本升级: 7.0.6 –> 7.0.7 后端版本升级: 7.0.6 –> 7.0.7 修复工作流回退节点导出的问题 修复低代码模型导入无代码字段时元数据差量计算错误的问题 20260608 升级内容 镜像版本升级: 7.0.5 –> 7.0.6 后端版本升级: 7.0.5.1 –> 7.0.6 修复工作流元数据导入找不到自定义函数的问题 修复工作流元数据导入导致流程重复触发的问题 20260129 升级内容 镜像版本升级: 7.0.4 –> 7.0.5 后端版本升级: 7.0.4 –> 7.0.5.1 前端版本升级 修复新模型的表格首次设置冻结渲染错误的问题 修复流程设计器数据权限表单字段丢失问题 修复业务流程抽屉转换为弹窗时高度异常的问题 20260117 升级内容 镜像版本升级: 7.0.3.1 –> 7.0.4 后端版本升级: 7.0.3 –> 7.0.4 前端版本升级 修复语言保存时毫秒格式验证错误的问题 修复界面设计器多对一表单配置提交函数过滤错误的问题 修复元数据导入时菜单无法更新动作的问题 修复工作流集成接口在某些情况下参数处理错误的问题 20260109 升级内容 升级此版本需要开启元数据全量刷新 pamirs.distribution.session.allMetaRefresh=true 镜像版本升级: 7.0.2 –> 7.0.3.1 后端版本升级: 7.0.2 –> 7.0.3 前端版本升级 修复工作流数据安装 增加对函数操作日志 增加函数操作规则设置 用户登录日志增加扩展点 时间格式支持毫秒 Eip日志增加毫秒支持 优化导出API 的文档结构 点击查看用户手册 集成接口日志参数信息支持 JSON/XML 格式切换及一键复制 点击查看用户手册 数据库 API 支持格式化 / 压缩SQL格式 点击查看用户手册 数据流程增加毫秒支持 语言增加毫秒支持 集成接口和开发接口日志统计增加日期范围筛选 增加标准心跳检查 trigger增加扩展点,适配多租户场景 增加导入文件URL错误,获取不到JSON的日志 解决元数据增强可能出现的死循环 修复集成设计器弹窗宽度问题 修复表格配置双击行动作,未预留动作区高度的问题 修复自定义 mask 变更 actionBar 插槽名称导致无法正常渲染的问题 20251229 升级内容 镜像版本升级: 7.0.1 –> 7.0.2 后端版本升级: 7.0.1 –> 7.0.2 前端版本升级 修复工作流元数据安装异常的问题 前端包名变更:@kunlun/vue-grid-layout@2.3.13 –> @oinone/vue-grid-layout@2.3.13 前端包名变更:webpack-aliyun-oss@0.5.2 –> @oinone/webpack-aliyun-oss@0.5.2 npmrc 统一配置 registry=https://registry.npmmirror.com/ @oinone:registry=http://nexus.shushi.pro/repository/kunlun/ legacy-peer-deps=true 20251220 升级内容 镜像版本升级: 7.0.0 –> 7.0.1 前端版本升级 界面设计器上传图片组件新增cdnKey配置 修复系统权限字段丢失导致无法正常运行的问题 修复全屏按钮悬浮文案 修复快捷键提示文案 修复取消排序展示错误的问题 修复快速填报选择不粘贴时数据处理错误的问题 修复流程设计器无法编辑流程名称的问题 修复移动端打包失败的问题 修复体验镜像RocketMQ无法正常启动的问题 20251217 升级内容 镜像版本升级: 7.0.0 后端版本升级: 7.0.1 前端版本升级 升级…

    2025年12月17日
    1.5K00

Leave a Reply

Please Login to Comment