<select id="listUser" resultType="hexie.practice.learn.elasticsearch.entity.User">
SELECT id, user_name, mobile, address FROM user LIMIT 0,#{size}
select>
@Autowired
private UserMapper userMapper;
@Test
void test() {
long l = System.currentTimeMillis();
List users = userMapper.listUser(7000000);
long l1 = System.currentTimeMillis();
System.out.println("耗时: " + (l1 - l) + "ms");
System.out.println(users.size());
// 215ms 247ms 292ms 490ms 2883ms 18500ms 62423ms
// 100 1000 10000 100000 1000000 5000000 7000000
}
我有一张表user, 里面有一千万个数据, 没加索引, 查询100个数据的时候花费了215ms, 1000个数据247ms, 10000个数据292ms, 如上所示, 为什么花费的时间不是简单的后面加个0?
而且在十万数据量之前, 都是按照差不多1.2的比例增长, 但从1百万开始就是6倍增长, 5百万和7百万的用时差了3.4倍, 为什么会出现这样的情况?
直接在Navicat里查的话, 1千万数据都不用8秒, 为什么放到代码里就要花费这么长时间?
这个问题原因比较复杂,解析基本如下:
1、你的表没有索引,查询条件也仅是记录限制,数据库的查询就是顺序读取记录。查询时间=读数据时间(从磁盘)+数据筛选时间,你这个单表顺序读,主要是读磁盘时间。
2、10-100万数据查询时间变化:数据库一般访问磁盘数据时是按页进行,一页大约多少行数据可以计算。因此查10、100、1000...都是读一页,因此耗费时间差不多。当超过一定行的时间后,就要读多页了。如10万到100万出现明显变化,可能10万仅1页,100万可能6-7页。
3、500到700万变化:这涉及到数据库缓存够不够,可能500万都读到内存处理即可,而700万时内存不够了,就要把结果缓存到磁盘上,因此时间会陡然增加。
4、最后说下程序时间比navicat长很多:navicat给出的响应时间就是发起数据库查询到形成结果所用时间。而程序中,还需要把结果一一映射成对象。当数据量很大时,生成对象是很耗时的,同时可能由于内存不够,还得用序列化到磁盘保存,这就更耗时。其实数据量不大,两者差异是不明显的,这就是大数据带来的挑战。
没有人会一下查这么多数据出来,都是分片
1、磁盘IO不同,随着数据的增长,那需要的磁盘IO次数也会增加,一次查询所需要的时间也会增加,并不是单纯的后面加个0
2、放在代码里,JDBC连接是负责和MYSQL通信的,会把sql语句发给MYSQL执行,可以看到MYSQL中,也会有线程获取到JDBC连接中的sql语句,然后去执行。
a.线程会把sql语句交给MYSQL中的sql接口,sql接口会转发给sql解析器去解析,比如,sql解析器会把一条sql语句中的表名称、WHERE关键字后面的查询条件、以及具体查询哪些字段等信息都解析出来,然后把解析好的信息交给查询优化器处理。
b.查询优化器会根据sql解析器解析好的sql语句信息,选择一个效率最高的处理方案,来作为执行sql语句的执行计划,然后转交给执行器去执行。
c.而执行器会调用MYSQL的存储引擎,这里我们用InnoDB存储引擎举例,InnoDB存储引擎中的接口就会来执行sql语句
所以花费时间更长。
参考:https://blog.csdn.net/qq_42046105/article/details/127286879
针对查询时间增加的问题,有以下可能的原因:
针对使用代码进行查询时间非常长的问题,可能的原因有以下几点:
针对以上可能的原因,可以采取以下措施进行优化:
同时,可以使用一些性能优化工具,如数据库性能监控工具、网络监控工具、线程监控工具等,进行数据性能诊断以及优化。