mysql limit过大 遍历的一些问题

博客围绕数据库查询需求展开,在从数据库中加载符合条件的大量数据时,使用limit查询,当offset很大时出现卡死问题。参考阿里巴巴Java开发手册进行优化,最终将耗时降低到6ms,且point_type字段无索引,还给出了相关参考资料链接。

最近有个需求,让把db里面某张符合条件的数据都load出来,数据量略大,当然不能一次都拉出来,那自然就想到了limit,sql如下

select  * 
from my_table
WHERE point_type=1003
order by id  limit 0,200

point_type 就是一个不带索引的普通字段

先是limit 0,1000 然后就是上一批数据的最大id,再次limit

但是很快就发生了问题,当offset很大的时候,sql基本就卡死了。

select  * 
from my_table
WHERE point_type =1003
limit 900000,200
-- 耗时 3181  

网上查了一点资料 - 阿里巴巴的java开发手册

 sql改成了如下:

select a.* 
from my_table a 
right join (
    select id 
    from my_table
    WHERE point_type =1003
    limit 900000,200
 ) b
on a.id = b.id

-- 680 ms


select a.* 
from my_table a ,
(
    select id 
    from my_table
    WHERE point_type =1003
    limit 900000,200
 ) b
where a.id = b.id

-- 690 ms

确实有优化,但是不管是on 还是 where ,时间还是有点长

改成如下,耗时降低到6ms。而且 point_type 这个字段上并没有索引(当然id上是有索引的)

select  * 
from my_table
WHERE id > 9427596100 and  point_type=1003
limit 1000
-- 6ms

当然这个9427596100,是上一次查询的时候,返回的最后一条数据的id


参考资料

sql的连接 
https://www.runoob.com/mysql/mysql-join.html
https://blog.youkuaiyun.com/Kermit_father/article/details/85937406

MySQL中,由于其语法限制,原生并没有数组数据结构,但你可以通过用户自定义变量(例如VARCHAR类型的字符串)模拟数组功能。如果你想在存储过程中遍历一个类似数组的数据,可以采用以下步骤: 1. 定义一个字符串,用逗号分隔每个元素。例如: ```sql DECLARE @array_string VARCHAR(4000) DEFAULT 'element1, element2, element3'; ``` 2. 将整个字符串分解成一个临时,然后逐个处理每个元素。可以使用FIND_IN_SET()函数配合SUBSTRING_INDEX()来做到这一点。比如: ```sql SET @array = (SELECT GROUP_CONCAT(TMP.element SEPARATOR ', ') FROM ( SELECT SUBSTRING_INDEX(@array_string, ',', n.n) as element FROM (SELECT a.N FROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 LIMIT 100) AS a(N) ) x(n) JOIN (SELECT @row := @row + 1 as row) r ON r.row = n.n ) TMP WHERE TMP.element != ''); ``` 这里,`GROUP_CONCAT()`将拆分后的元素合并回一个字符串,`SUBSTRING_INDEX()`用于获取指定位置的元素,`LIMIT 100`是为了避免一次性处理过长的字符串。 3. 遍历这个临时`TMP`,对每个元素执行你需要的操作。例如: ```sql WHILE @array != '' DO SET @current_element = SUBSTRING_INDEX(@array, ',', 1); -- 执行与当前元素相关的操作 SELECT * FROM your_table WHERE condition LIKE CONCAT('%', @current_element, '%'); SET @array = SUBSTRING(@array, LENGTH(@current_element) + 2); END WHILE; ``` 注意,这种方法效率不高,特别是对于型数组,因为它涉及到多次字符串分割。如果性能很重要,你可能需要考虑其他数据库系统,如PostgreSQL,它们提供了更好的数组处理能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值