广告
返回顶部
首页 > 资讯 > 数据库 >浅谈Mysql大数据分页查询解决方案
  • 330
分享到

浅谈Mysql大数据分页查询解决方案

2024-04-02 19:04:59 330人浏览 安东尼
摘要

目录1.简介2.分页插件使用3.sql测试与分析3.1 limit现象分析3.2 解决之道4 测试时走过的坑4.1 百万数据内容都一样4.2 写sql时,把"77"

1.简介

之前,面阿里的时候,有个面试官问我有没有使用过分页查询,我说有,他说分页查询是有问题的,怎么解决;后来这个问题我没有回答出来;本着学习的态度,今天来解决一下这个问题;

2.分页插件使用

1.pom文件

        <dependency>
            <groupId>com.GitHub.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.6</version>
        </dependency>

2.创建分页配置器

@Configuration
public class PageHelperConfig {
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        pageHelper.setProperties(p);
        return pageHelper;
    }
}
  • 测试代码:
    @Test
    void test() {
        PageHelper.startPage(400000,10,"id desc");
        List<UploadData> users = userMapper.queryAll();
        System.out.println(users.size());
        System.out.println(users);
        for (UploadData uploadData: users) {
            System.out.println(uploadData);
        }
    }

4.重写sql分析

debug 后可以查看它是通过重写sql来实现分页功能; 重写后的sql语句为"SELECT * FROM amj_devinfo order by id desc limit ?, ?";
limit a, b;// 跳过前a条数据,取b条数据;
所以,其实现在问题就是回到了,执行这条sql语句所需要花费多少的问题了;

3.sql测试与分析

select * from amj_devinfo order by id limit 2000, 20;     // 0.027s
select * from amj_devinfo order by id limit 20000, 20;    // 0.035s
select * from amj_devinfo order by id limit 200000, 20;   // 0.136s
select * from amj_devinfo order by id limit 2000000, 20;  // 1.484s

select * from amj_devinfo order by devaddress limit 2000000, 20; // 7.356 全表扫描 + filesort;

结论:如果说,是小的数据量的话,使用该分页完全没问题;当数据量到达两百万的时候,执行时间就得为6.729s了,对于用户来说,这是不可接受的;

3.1 limit现象分析

使用explain对sql先来分析一波;感兴趣的同学可以看看我的另一篇文章 Mysql结合explain分析结果如下:

针对,select * from amj_devinfo order by id limit 2000, 20来说:

可以看到,使用的是基于索引树 + 回表的方法来获取数据的,顺序IO查询列数为:2000020; 首先,根据阿里Java开发手册,type为index 就已经不可接受了;最低标准为range;而且,它是order by id 能够使用上主键索引,要是order by '其他列(无索引)如devaddress' 这个时候,就是全表扫描 + filesort,效率更慢;
备注

select * from amj_devinfo order by id limit 2000000, 20;

这条语句是 方案一 :先通过id找到2000000,然后,剩下的20条再全表扫描;还是,方案二: 通过id回表直接找到2000020条,然后,放弃前2000000条;理论上剩下20条进行全表扫描肯定是快很多的;但是,有点尴尬。mysql选择的其实是方案二;

3.2 解决之道

很显然,现在已经是发现了问题所在,我们需要对其进行解决;我们对下面的sql语句来进行升级;

测试背景:
1.mysql 数据表中有5695594 (五百万)条数据,在devcho中数据相对离散。
2.表的设计如下:

有需要测试的同学,可以按照我表设计来模拟测试;

select * from amj_devinfo where devcho = "77" limit 20000, 10;

3.2.1 对devcho建立索引

很显然,通过sql来查询的话,对devcho建立索引的话,可以把全表扫描升级为基于索引列的扫描;能提升一个量级;
索引建立结果如下:

执行sql语句

执行时间8.415s 这个时间是不可以接收的;

3.2.2 sql执行时间长分析

经过多次测试,发现时间都是很久,那么,就不会是Mysql 刷脏页,而且,数据库空闲,没有别的sql与其竞争磁盘IO 而且,通过mvcC查找数据也不存在相关问题;所以,问题肯定是出现在sql语句上;
那么,为什么会出现这个问题呢? -- 答案是回表这条sql语句是怎么执行的呢?

  • 先基于devcho的索引列,找到devcho='77'的这一行;
  • 在通过devcho中存的主键id,然后,回表找所有的数据;找20010条数据;

这时候,问题就出现了,这个回表的过程是随机IO;这个随机IO效率是很低的;所以,undo log要把随机IO变成顺序IO。这里,就是最大的瓶颈所在;
扫描条数验证: Handler_read_next: 该选项表明在进行索引扫描时,按照索引从文件数据里取数据的次数;

回表是sql瓶颈验证:

查找主键id,不需要回表,发现0.01s就可以搞定;证明了sql导致的回表就是瓶颈所在;

3.2.3 解决之道

我们刚刚发现,因为limit比较笨。select * from amj_devinfo where devcho = "77" limit 20000, 10;需要回表20010次;但是,我们只需要它回表10次啊。所以,我们可以先把符合条件的id找出来;再根据id使用inner join 去进行回表;
sql语句如下:

select * from amj_devinfo a INNER JOIN (select id from amj_devinfo where devcho = "77" limit 20000, 10) b on a.id = b.id;

查询时间:0.025s

这个时候,就可以达到我们的要求了;这个联结是会产生笛卡尔积的。检索出来行的数目是第一个表中的行数乘以第二个表中的行数,以前,感觉挺慢的,这也证明,如果没有文件排序或者临时表的话,效率其实还可以;

4 测试时走过的坑

在测试的时候,其实我犯了两个错,卡了自己好几个小时,证明测试都不对;特此记录一下,给想复现现象的同学提个醒;

  • 插入百万条数据数据内容相同;
  • 在执行sql时,格式没有对应上,导致索引失效select * from amj_devinfo where devcho = 77 limit 20000, 10; 77是字符,我输入为整型;

4.1 百万数据内容都一样

select * from amj_devinfo where devcho = "2212" limit 20000, 10; // 0.042s
select id from amj_devinfo where devcho = "2212" limit 20000, 10; // 0.026s

还是上面的语句,只是数据内容是一样的;为什么两者时间是一个级别?
为什么会产生这种现象呢?

  • 因为数据都一样的devcho 索引其实是没有用的;成为链表了;
  • 第一条语句,找出20010条语句就找到内容了,因为,都存在一起 都在一个或者几个页表中,随机IO升级为顺序IO,是有回表,但是,顺序IO的回表也是很快的。 所以,效率很高;即,第一条语句和第二条语句花的时间是差不多的;

4.2 写sql时,把"77"写成了77;

现象再现:

select id from amj_devinfo where devcho = 77 limit 20000, 10; // 查询时间2.064s
select * from amj_devinfo where devcho = 77 limit 20000, 10; // 查询时间3.716s

这里 第一条语句因为字段比第二条语句中少;所以,放入sort_buffer中的数据是不同的;
问题回顾:我之前就在想,为什么我基于索引列查询id会这么慢?我当时没想到索引失效问题;后来,我是怎么发现这个问题的呢?因为,基于索引列查询的时候,Mysql要扫描的字段也就是20010条数据即可;而我查看Handler_read_next(此选项表明在进行索引扫描时,按照索引从数据文件里取数据的次数)时,

Handler_read_next 4274160 

explain分析结果:

如果,扫描这么多行,需要这么多时间是可以理解的,那么,为什么需要扫描这么多行呢? 我那时候,重新看了一下表的设计,发现原来devcho字段的类型是varchar;这个时候,就想到了索引失效这个问题;

4.2.1 为什么会索引失效?

既然,发现了类型不同导致索引失效,那么就分析一下,为什么会导致索引失效?这条sql又将如何执行? 因为,他是基于索引列找的。但是,由于77 != '77'所以,这就导致了索引实现;但是,最终它还是找到了数据,这个时候,结合了扫描行数,我个人感觉应该是采用了全表扫描,然后,通过,强制类型转换,cpu进行判断,查询所得;
当改成 select id from amj_devinfo where devcho = "77" limit 20000, 10;就没有这个问题了;扫描的行数为20009行; 所以,在写sql语句的过程中还是要注意啊;
字段为varchar 传入 int 会索引失效,那么,字段为bigint 传入 "String" 会失效吗?经过测试:不会失效;

所以,在mybatis中,可以放心使用#{}占位符了;

4.3 一个有趣的现象

大扫描行数 VS 随机IO

select * from amj_devinfo  where devcho  = 77 limit 20000, 10; 查询时间 3.311s
select * from amj_devinfo  where devcho  = "77" limit 20000, 10; 查询时间 3.188s

第一个sql扫描的行数是500多万行; 但是,由于每个行都需要读入内存中,使用的是顺序IO 第二个sql扫描的行数是20010行,但是,需要访问随机IO 20010次;其实,基本上也就把所有的页表都找了一次;
小总结:随机IO,查询次数都要避免;

总结

本文,主要是模拟了分页查询中,往后数据查询较慢的现象,以及分析了速度较慢的原因;limit导致随机回表数增多。并提供了解决方法,先找到符合条件的id;然后,根据id做内联查询,减少随机IO的次数;并且,总结了一下自己出现的问题以及原因;如果,有一些个人见解不一定正确的话,希望大家多多指正;

到此这篇关于浅谈Mysql大数据分页查询解决方案的文章就介绍到这了,更多相关Mysql大数据分页查询 内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: 浅谈Mysql大数据分页查询解决方案

本文链接: https://www.lsjlt.com/news/139629.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 浅谈Mysql大数据分页查询解决方案
    目录1.简介2.分页插件使用3.sql测试与分析3.1 limit现象分析3.2 解决之道4 测试时走过的坑4.1 百万数据内容都一样4.2 写sql时,把"77"...
    99+
    2022-11-13
  • MySql查询不区分大小写解决方案
    背景 当我们输入不管大小写都能查询到数据,例如:输入 lingyejun 或者Lingyejun ,LingYeJun都能查询同样的结果,说明查询条件对大小写不敏感。CREATE TABLE NAME(name VARCHAR(1...
    99+
    2023-09-05
    mysql 数据库 sql mybatis java
  • MySQL百万级数据分页查询优化方案
    当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询。对于数据库分页查询,也有很多种方法和优化的点。下面简单说一下我知道的一些方法。 ...
    99+
    2022-10-18
  • 优化mysql大表分页查询翻页的具体方案
    下文我给大家简单讲讲关于优化mysql大表分页查询翻页的具体方案,大家之前了解过相关类似主题内容吗?感兴趣的话就一起来看看这篇文章吧,相信看完优化mysql大表分页查询翻页的具体方案对大家多少有点帮助吧。&...
    99+
    2022-10-18
  • Mybatis-Plus分页插件查询慢解决方案
    问题 需求反馈前端界面查询速度很慢。 分析 f12查看接口响应时间达到了5.47s。 查看后端代码逻辑,就是传了些参数,分页查询了一个列表的数据。分页插件使用的是mybatis-plus...
    99+
    2023-09-01
    mybatis mysql spring boot Powered by 金山文档
  • 大数据中自助查询的解决方案是什么
    今天给大家介绍一下大数据中自助查询的解决方案是什么。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。如果你曾经出国旅游,尤其是去欧洲自由行,有没有在餐馆点菜的惨痛...
    99+
    2023-06-04
  • 解决MySQL查询不区分大小写的方法
    本篇内容主要讲解“解决MySQL查询不区分大小写的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“解决MySQL查询不区分大小写的方法”吧!今天遇到一个情况,...
    99+
    2022-10-18
  • Mybatis Plus一对多联表查询及分页解决方案
    文章目录 需求需求分析分页问题说明分页问题原因一对多场景一一对多场景二性能优化优化解决方案 需求 查询用户信息列表,其中包含用户对应角色信息,页面检索条件有根据角色名称查询用户列...
    99+
    2023-10-22
    mybatis java 开发语言
  • SQL数据库容量大,查询速度慢,有何解决方案?
    首先应该确定是谁慢的,往往是程序处理方面的问题而不是数据库的问题。 程序方面应该尽可能的减少数据查询返回的内容,比如可以查询返回ID,然后再根据ID一条一条的查询具体内容,看似慢了,在数据量达的时候快很多 对于数据可以参照下面几点 1、优化...
    99+
    2023-09-02
    数据库 oracle mysql
  • 解决MySQl查询不区分大小写的方法讲解
    问题 最近,在用SSH框架完成一个实践项目时,碰到了一个莫名其妙的Bug困扰了我好久,最后终于解决,记录如下。 问题:同学在测试系统的时候突然发现,数据库保存的账户本来应该是admin,结果该同学用Adm...
    99+
    2022-10-18
  • MySQL百万级数据大分页查询优化的实现
    目录一、MySQL分页起点越大查询速度越慢二、 limit大分页问题的性能优化方法(1)利用表的覆盖索引来加速分页查询(2)用上次分页的最大id优化三、MySQL百万数据快速生成3....
    99+
    2022-11-12
  • mysql数据库中分页查询的使用方法
    这篇文章给大家分享的是有关mysql数据库中分页查询的使用方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。作用:把行按照字段分组Select column,...
    99+
    2022-10-18
  • mysql数据库分页查询的方法是什么
    MySQL数据库分页查询的方法是使用LIMIT关键字来限制查询结果的返回行数。LIMIT子句可以在SELECT语句中使用,其...
    99+
    2023-08-30
    mysql数据库
  • mysql字段数据为null时反查询不到的解决方案
     当我们通过 mysql 使用 NOT IN 查询时,如果条件字段可以为 NULL 并且值为NULL需要特别注意一下这个时候使用 NOT IN 查询时是查询不到的。测试NULL时反查询不到例子假如我们现在有一个表 useridnicknam...
    99+
    2022-06-17
    MySql 优化 解决方案 数据库
  • 数据库高并发解决方案——查询优化
      查询优化 ①保证在实现功能的基础上,尽量减少对数据库的访问次数; ②通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担; ③能够分开的操作尽量分开处理,提高每次的响应...
    99+
    2020-07-29
    数据库高并发解决方案——查询优化
  • vue查询数据el-table不更新数据的解决方案
    目录vue查询到数据el-table不更新数据解决方案vue查询到数据el-table不更新数据 如:查询名称为abc的数据,.js及.vue后台打印都可以查询到此条数据,el-ta...
    99+
    2022-12-15
    vue查询数据el-table不更新数据 vue el-table数据不更新
  • Python查询oracle数据库速度慢的解决方案
    如下所示: conn = cx_Oracle.connect('username/password@ip:port/servername') cur = conn.cursor(...
    99+
    2022-11-12
  • MySQL大数据表处理的三种方案,查询效率嘎嘎高
    场景 当我们业务数据库表中的数据越来越多,如果你也和我遇到了以下类似场景,那让我们一起来解决这个问题 数据的插入,查询时长较长后续业务需求的扩展 在表中新增字段 影响较大表中的数据并不是所有的都为有效数据 需求只查询时间区间内的 评估表数据...
    99+
    2023-08-30
    mysql 大数据 数据库
  • MySQL千万级数据的大表优化解决方案
    目录1.数据库设计和表创建时就要考虑性能设计表时要注意:索引简言之就是使用合适的数据类型,选择合适的索引引擎2.sql的编写需要注意优化3.分区分区的好处是:分区的限制和缺点:分区的类型:4.分表5.分库mysql数据库...
    99+
    2022-11-20
    mysql千万级数据 mysql优化
  • mysql一对多关联查询分页错误问题的解决方法
    xml问价中查询数据中包含list,需要使用collection <resultMap id="XX" type="com.XXX.XXXX"> <id column="o_i...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作