使用两种方式在 mysql 中实现计算10万条数据的排名

文章讲述了在MySQL数据库中,作者对比了子查询和MySQL8的窗口函数(RANK和DENSE_RANK)在处理排名连续和不连续问题上的性能差异,发现窗口函数在处理大量数据时效率显著提高,推荐在大数据场景下使用窗口函数进行排名查询。

需求中有一点这样的功能,我这边在本地 mysql 做了实现并测试,发现如果自己写基本上跑不出来 10 万条数据,但是使用 mysql8 中自带的窗口函数就会非常之快

首先需要讲一下,排名结果大致分为两种,一种是排名连续,另外一种是排名不连续。例如有三个同学 A B C,A100分,B100分,C90分,那么在排名连续的情况下,A和B都是第一名,C是第二名;如果是排名不连续的情况下,A和B同样的,都是第一名,但是C是第三名。

1. 子查询实现

tips: 无法跑通 10 万条数据

-- 1. 排名不中断
SELECT
	a.score,
	(
		SELECT count( DISTINCT b.score ) + 1 
		FROM scores b WHERE b.score > a.score 
	) AS 'rank'
FROM
	scores a 
ORDER BY
	score DESC;
	
-- 2. 排名中断
SELECT
	a.score,
	(
		SELECT count( 1 ) + 1
		FROM scores b WHERE b.score > a.score
	) AS 'rank'
FROM
	scores a 
ORDER BY
	score DESC;

2. 使用窗口函数(mysql8)

tips:平均用时0.28秒,非常之快!

-- 1. 排名中断
SELECT
	score
	RANK() over ( ORDER BY score DESC ) AS 'rank' 
FROM
	scores;
	
-- 2. 排名连续
SELECT
	score,
	DENSE_RANK() over ( ORDER BY score DESC ) AS 'rank' 
FROM
	scores;

以上测试的结果供大家参考,如果数据量大的话,需要使用 sql 中将排名查出来,建议最好使用窗口函数。

### 数据分页查询与缓存策略 在处理十万数据的查询功能时,为了确保系统的性能和响应速度,可以采用多种优化策略。一种常见的方法是使用数据库的分页查询机制。例如,在MySQL中,可以通过`LIMIT`和`OFFSET`关键字来实现分页查询,这样可以在每次请求时只加载一部分数据到内存中,从而减少服务器的压力。 ```sql SELECT * FROM table_name LIMIT 1000 OFFSET 0; ``` 上述SQL语句会从表中获取1000记录,通过改变`OFFSET`值,可以获取下一页的数据。这种方法适用于数据量不是特别巨大的情况[^1]。 ### 使用批处理技术 除了分页查询外,还可以利用批处理技术来提高效率。如之提到的MyBatis批处理操作,将每一定数量的数据放在一个批次中处理,能够较为有效地提高处理速度。同时需要注意的是,在循环处理时要带有合适的等待时间和批处理大小,以防止出现内存占用过高等问题。此外,还需要在配置文件中设置合理的连接池和数据库的参数,以获得更好的性能[^1]。 ### 数据分片处理 对于端来说,如果需要处理大量的数据,可以采用数据分片的方法。即将大数据集分割成较小的部分,逐个处理这些小部分的数据。这样做可以避免一次性处理大量数据所带来的性能问题,提高页面的响应速度[^2]。 ### 内存管理与流式处理 当涉及到非常大的数据集时,必须考虑到内存限制。在这种情况下,可以考虑使用流式处理技术,即按需读取和处理数据,而不是一次性加载所有数据到内存中。这种方式特别适合于内存受限的情况,因为它允许程序在任何时候都只保持一小部分数据在内存中[^3]。 ### 虚拟滚动与Web Worker 对于端渲染大量数据的情况,可以采用虚拟滚动技术,只渲染可视区域内的元素,而不在屏幕上的元素则不会被创建或更新,以此减少DOM节点的数量,提升性能。另外,还可以利用Web Worker来进行数据预处理,这样可以在不影响主线程的情况下完成计算密集型任务,保持UI的流畅性[^4]。 ### 示例代码 - 分页查询 下面是一个简单的Python示例,展示如何使用分页查询来逐步获取数据: ```python def get_data(page_size, offset): # 连接数据库并执行查询 connection = establish_connection() cursor = connection.cursor() query = f"SELECT * FROM large_table LIMIT {page_size} OFFSET {offset}" cursor.execute(query) results = cursor.fetchall() # 处理结果... return results # 获取第一页数据,每页1000记录 first_page = get_data(1000, 0) # 获取第二页数据 second_page = get_data(1000, 1000) ``` 这个例子中的函数`get_data`接收两个参数:`page_size`表示每页的记录数,`offset`表示偏移量,也就是起始位置。通过调整这两个参数,可以轻松地遍历整个数据集。 ### 总结 综上所述,高效实现十万数据的查询和处理涉及到了后端的数据分页、批处理以及端的数据分片、虚拟滚动等技术。结合适当的内存管理和异步处理技术,可以显著提升应用程序的整体性能和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值