MySQL深分页 + 多字段排序场景的优化方案【三百万级数据量】

news2024/11/14 15:27:48

需求背景

目前产品需要针对一个大范围地区内的所有用户做排行榜功能,且这个排行榜有几个比较蛋疼的附加需求:

  1. 排行榜需要全量展示所有用户,且做分页展示(大坑💥)
    在这里插入图片描述
  2. 排行榜有4种排序条件,且每个排序条件都是单独的。例如:用户的应用A下载数、应用B下载数、应用C下载数、应用D下载数(产品不期望把所有的数据整合成一块进行排名)
    在这里插入图片描述

历史代码背景

其实这个需求已经够扯了,雪上加霜的是,以前的开发者在开发排行榜的时候,由于需求背景原因,采用了多表join的方式来进行查询。

这是什么意思呢?这里详细说一下:

假设有一张表C,就是排行榜的单表数;
目前无法直接从表C中拿到排行榜的所有所需字段。
(听说是需求原因,别无他法)

导致了开发者在MyBatis层面通过多表join的方式补充了所需字段;
最后SQL就是:table A left join table B left join table C

以上方式进行多表join,先不说分页、排序等性能问题。单纯表A join 表B都已经耗时3秒(表A数据量250W、表B数据量300W)

优化点一:多表join优化

针对多表join的问题,必须想尽办法把多表join的查询操作改为单表查询,否则多表join随着数据量增加,后期性能不敢想象

优化点二:优化SQL,避免深分页所带来的问题

select * from table A t1 join (
	select id from table A 
	order by indexA des 
	limit 20000, 20
) t2 on t1.id = t2.id

这里通过子查询的方式,且限制分页的页数(注意,虽然pageSize = 20000,MySQL会扫描前20000个数据,然后再从20001开始拿数据,再丢弃前20000条数据,因此还是会顺序扫前面的20000条数据,而不是跳到20001开始扫描的。这里可以网上查资料学习下)

此SQL还有优化空间,就是在临时的子表中补充上where条件,就可以直接筛选掉大部分无效数据

select * from table A t1 join (
	select id from table A  
	where index_value > 100000 
	order by indexA des 
	limit 20000, 20
) t2 on t1.id = t2.id

抛出一个问题

  • MySQL的in和join,谁的性能更好?

在本次开发过程中,in的方式指定查询大量数据,发现DB查询超时了;只有使用join的方式才能查到数据,这是为什么?

优化点三:深分页,设定阈值合理倒序查询

其实深分页最主要的问题就是 limit m, n 这个偏移量的问题;如果正序数,拿最后一页数据,相当于扫描前m个数据,再从m+1开始拿到m+n;

仔细想想,这个地方,如果正序拿最后一页,那不如我直接倒序拿第一页?这样的话,就规避了深分页问题,这个一般会设定一个阈值,超过阈值就进行正序 / 倒序

优化点四:排序字段单独建立索引

其实针对排序字段,一般会补充索引来进行优化,因此多字段排序的话,尽量让每个排序字段都单独设置一个索引,因为索引已经帮我们做好排序了。

这里要注意一个点,尽量不要接多字段同时排序的需求,这种情况下索引的设计将会十分复杂

优化点五:单表拆分

因为表C有多个排序字段,且还有各种where条件筛选,此时如果建立联合索引来解决的话,因为需要满足 最左匹配原则,此时联合索引的数量将会很大,届时索引树也会十分复杂。还好排行榜是读多写少的表数据,否则性能堪忧;

此时其实更建议进行单表的拆分,让每一个表所负责的职责更加明确;因为以前的表C,相当于就是把多个排行榜冗余在一个单表中了,这时候表C的压力是很大的。因此单表拆分,此时针对单表的排序字段建立对应的索引,且单表职责更加单一;

单表拆分方案:

  1. 查询某个字段的排序数据时,在MyBatis层面,根据排序字段,指定查询排序字段所对应的单表。
  2. 单表拆分后,需要合理创建索引

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

fatal error怎么解决,有什么快捷的解决方法

fatal error怎么解决,其实是有多种的解决方法的,主要是看你想用哪种解决方法去进行解决,下面一起来看看。 一.fatal error的解决方法 1、按winR,弹出运行窗口。 2、输入regedit点击确定,弹出注册表编辑器。 3、在注…

2023年数据库优化顶级原理

毫不夸张的说咱们后端工程师,无论在哪家公司,呆在哪个团队,做哪个系统,遇到的第一个让人头疼的问题绝对是数据库性能问题。如果我们有一套成熟的方法论,能让大家快速、准确的去选择出合适的优化方案,我相信…

Acwing-1116. 马走日

本题求有多少路径遍历棋盘上的所有点,属于外部搜索,所以需要回溯。另外,对于递归终止条件,我们添加一个参数用来表示当前遍历到第几个点,如果是n*m表明已经将棋盘遍历一遍了,方案数1,return即可…

Linux常用命令——screen命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) screen 用于命令行终端切换 补充说明 Screen是一款由GNU计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话,并在其间自由切换。GNU Screen可以看作是…

Linux学习笔记本(不定期持续更新)

一、概述 2023年,打算系统自学一遍Linux,分享到这里来,和大家一起相互学习,探讨。 二、Linux基础知识 Linux学习环境搭建学习每一门技术,系统环境很重要,好的系统环境能够极大提高学习效率。学习Linux也是一…

33. 实战:实现某网站店铺信息的查询与批量抓取(附源码)

目录 前言 目的 思路 代码实现 1. 请求URL,获取源代码 2. 解析源代码,获取数据 3. 完善保存数据的函数save_data 4. 理清main函数逻辑,循环传递每一页有效信息的参数 完整代码 运行效果 总结 前言 近日,我们每周四都能…

ESP-C3入门5. 使用通用计时器

ESP-C3入门5. 使用通用计时器一、 简介二、使用步骤三、操作函数1. 基本操作(1)定时器实例 gptimer_handle_t (2) 定时器配置结构体 gptimer_config_t(3) 定时器初始化 timer_init()(3&#xff…

探索 Vue.js 中引用的力量:访问和操作 DOM 元素”

0.简介 Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它由 Evan You 于 2014 年创建,此后作为构建 Web 应用程序的工具越来越受欢迎。 Vue 的核心特性包括: 反应式数据绑定:Vue 使用反应式系统来跟踪对数据模型的更改并自动更新…

22年部署之docker学习

以下记录的是,我在学习中的一些学习笔记,这篇笔记是自己学习的学习大杂烩,主要用于记录,方便查找https://hub.docker.com/ 镜像中心Docker 常用命令: docker 运行相关运行: service docker start停止&#…

【三年面试五年模拟】算法工程师的独孤九剑秘籍(前十二式汇总篇)V1版

写在前面 【三年面试五年模拟】栏目专注于分享AI行业中实习/校招/社招维度的必备面积知识点与面试方法,并向着更实战,更真实,更从容的方向不断优化迭代。也欢迎大家提出宝贵的意见或优化ideas,一起交流学习💪 大家好&a…

ABB机器人系统输入输出信号System Input和Output详解(一)

ABB机器人系统输入输出信号System Input和Output详解 System Input类型: 输入I/O信号可指定具体的系统输入项,比如Start或Motors on。该输入项会在不使用FlexPendant示教器或其它硬件装置的情况下触发一项交由系统处理的系统行动。 可以用一个PLC来触发相应的系统输入项。 注…

Node.js教程笔记(三)express

学习目标 能够使用express.static()快速托管静态资源 能够使用express路由精简项目结构 能够使用常见的express中间件 能够使用express创建API接口 能够在express中启用cors跨域资源共享 目录 初识Express Express路由 Express中间件 使用Express写接口 1、初识Expres…

【通信原理(含matlab程序)】实验三 数字基带信号及其频谱特性

💥💥💞💞欢迎来到本博客❤️❤️💥💥 本人持续分享更多关于电子通信专业内容以及嵌入式和单片机的知识,如果大家喜欢,别忘点个赞加个关注哦,让我们一起共同进步~ &#x…

Android OpenCV(二)主体识别 位置检测

前言 工作中遇到需要通过OpenCV找到图片主体体积占图片百分比的比例,这里做一个问题解决思路的记录。该方面新手小白,有不对的地方可以评论指出哈 。 重要API Sobel算法 Sobel 计算参考文章 索贝尔算子是计算机视觉领域的一种重要处理方法。 主要用于…

内网传输——解决物联网信息安全和隐私保护问题

与普通电脑系统不同,物联网建立在嵌入式系统的基础之上,其通信协议因设备和应用程序而异。目前还没有一个统一的中央系统来构建安全措施,那么,在企业物联网实际应用中,如何保证信息安全?物联网生态系统的安…

OpenHarmony社区运营报告(2022年12月)

本月快讯• 本月新增22款产品通过兼容性测评,累计220款产品通过兼容性测评。• 12月28日,OpenAtom OpenHarmony(以下简称“OpenHarmony”)凭借其创新的技术特性和开源生态建设成果,荣膺“InfoQ 2022年度十大开源新锐项…

Redis实现用户签到 | 黑马点评

目录 一、BitMap用法 1、介绍 2、用法 3、练习 二、签到功能 1、需求 2、代码实现 三、签到统计 1、分析 2、接口实现 一、BitMap用法 1、介绍 我们完全可以通过数据库签到表来实现签到功能,但是假如我们的用户达到千万,每年平均签到10次&am…

基于微信小程序的网络安全科普系统小程序

文末联系获取源码 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.…

设计模式之简单工厂

现在有一个这样的需求:控制台输入俩个数,并输入运算符,计算并输出结果。上述需求乍一看,特别像一个小型的计算器,记得初学Java时,实现过。 实现一: 创建计算器类,控制台输入俩个数…

windows 10 本地配置Oracle19+用navicat连接

文章目录0.背景环境0.背景知识1.卸载旧版本、安装 oracle 192.配置3.用 Navicat 连接3.1 下载instantclient193.2 配置dll使能连接高版本oracle3.3 配置连接4. 相关操作命令5.本地命令行登录orclpdb下的用户0.背景环境 本机已安装oracle12和Navicat15,需要先彻底卸载…