首页 > 技术文章 > 【实战】利用多线程优化查询百万级数据

iamamg97 2021-11-19 21:04 原文

前言

日常开发中,难免会遇到需要查询到数据库所有记录的业务场景,在索引完善的情况下,当数据量达到百万级别或者以上的时候,全表查询就需要耗费不少的时间,这时候我们可以从以下几个方向着手优化

  1. 优化sql

  2. 利用多线程查询

  3. 分库分表

今天就来讨论一下使用【优化sql】和【多线程】方式提升全表查询效率

⚠️注意,这只是简单测试,用于讲解思路,真实情况会更加的复杂,效率可能会相对受到影响,而且也会受硬件配置的影响,所以不是绝对的

前置准备

  1. 使用InnoDb作为执行引擎

  2. 创建测试表,有自增主键id

  3. 往表中添加测试数据(100W以上),可以选择在程序中导入,也可以选择在数据库里面生成测试数据,具体可以参考:生成测试数据

  4. Java程序中使用Mybatis来操作,使用自定义注解+SpringAOP的方式来记录执行耗时,源码后面会给,有兴趣的朋友可以下载下来实践一下

  5. 总体目录结构

    image

开始测试

首先确保库中是有数据的,由于实际业务的复杂度,所以这里模拟username的时候也让他复杂一点,不是同一条数据进行了600多万次复制

image

image

单线程+基础sql

再下来就是基础的全表查询方式,这里使用postman测试

@GetMapping("/sync")
public String getData() {
    List<User> list = userService.queryAllUseSync();
    return "查询成功!";
}


@Override
@RecordMethodSpendAnnotation //这个注解标记的方法会被SpringAOP管理起来,计算方法耗时
public List<User> queryAllUseSync() {

    //直接就采用Mybatis全查
    return userMapper.queryAll();
}

image

我们来看一下,这个queryAll的sql,可以发现就是一个简单的全表查询

<select id="queryAll" resultMap="UserMap">
		select
		id, username, create_time
		from performance.user
</select>
原因分析

我们直接把sql抓出来EXPLAIN一下,可以发现是没有走索引的,全表600多W的数据,本机耗时(多次测试取平均):67s

image

推荐阅读