前言

:“redis为什么比Mysql快?”

我相信这是大家只要学过redis或者看过面试题都会遇到也都会回答的一个问题。那么,我突然想到一个问题:redis一定比mysql快吗?

答案是:不一定!

今天看着黑马点评的项目,突然想到,redis是不是一定比mysql快呢?所以就去各大主流程序员网站进行搜索,包括掘金,csdn。只在csdn中只找到了一篇文章有进行对比测试,采用jmeter测试得出redis比mysql快接近6倍。

01.掘金搜索结果

02.csdn搜索结果

没找到答案的我,针对于这个疑问,我做了以下几场测试。

测试1

测试1测试平台如下

1
2
3
4
mysql-8.0.29  在本机运行
虚拟机CentOS7.6 分一核二线程,2G运行内存
redis-6.2.6 在虚拟机运行
测试数据库hmdp中,tb_user表查询

这里我们先连接上本机的数据库,并在redis中添加key为user的数据。

03.测试1配置

04.redis增加数据

编写连接测试的代码,运行后可以拿到两边的测试数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Resource
private StringRedisTemplate stringRedisTemplate;

@Resource
private UserServiceImpl userService;

@Test
void testMysql() {
User mysqlValue = userService.query().eq("id", 1).one();
System.out.println("mysql连接成功,查询的值为" + mysqlValue);
String redisValue = stringRedisTemplate.opsForValue().get("user");
System.out.println("redis连接成功,查询的值为" + redisValue);
}

05.测试链接

测试编写代码,大量查询redis和mysql,这里我们分别查询1次,10次,100次,1000次,10000次,100000次比较结果。测试代码和结果如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Resource
private StringRedisTemplate stringRedisTemplate;

@Resource
private UserServiceImpl userService;

@Test
void testRedisAndMysql() {
int times = 1;
long start;
long end;
for (int i = 0; i < 6; i++) {
start = System.currentTimeMillis();
for (int j = 0; j < times; j++) {
userService.query().eq("id",1).count();
}
end = System.currentTimeMillis();
System.out.println(times + "次 \t查询mysql数据库耗时" + (end - start) + "ms");
start = System.currentTimeMillis();
for (int j = 0; j < times; j++) {
stringRedisTemplate.opsForValue().get("user");
}
end = System.currentTimeMillis();
System.out.println(times + "次 \t查询redis数据库耗时" + (end - start) + "ms");
times = times * 10;
}
}

06.第一次比较结果

07.01.第一次比较结果柱状图

07.02.第一次比较结果柱状图

第一次查询两者都耗时较久,这归因于启动项目后第一次建立连接的原因,也算是为后面的几轮测试做好初始化。

不难发现,结果可谓是令人大跌眼镜啊!在数据量较小时,1000次以下时,redis还是明显比mysql要快的,但是还是无法做到好几倍的优化效果。当数据量来到到一万次时,redis居然直接被mysql甩下一个身位!?!?这是为什么??要知道,redis存储的user数据,是用key去直接读取的;mysql的tb_user表下还有上千条数据,使用B+树排序搜索的。

是不是因为mysql的环境就直接和idea都在本机?而redis运行在虚拟机上?

带着这个疑问,我又在虚拟机上安装了mysql数据库,创建了一个user表,只增加了一条数据。(这里安装mysql和远程连接又踩了很多坑,看到这里的小伙伴看在我被坑的不浅的份上,可以留下一个大大的赞吗~)

测试2

测试2测试平台如下

1
2
3
4
虚拟机CentOS7.6 分一核二线程,2G运行内存
mysql-5.7.26 在虚拟机运行
redis-6.2.6 在虚拟机运行
测试数据库hmdp中,tb_user表查询(只有一条数据)

更改配置文件,连接数据库,并运行测试代码测试是否连接成功连接。

08.测试2的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
@Resource
private StringRedisTemplate stringRedisTemplate;

@Resource
private UserServiceImpl userService;

@Test
void testMysql() {
User mysqlValue = userService.query().eq("id", 1).one();
System.out.println("mysql连接成功,查询的值为" + mysqlValue);
String redisValue = stringRedisTemplate.opsForValue().get("user");
System.out.println("redis连接成功,查询的值为" + redisValue);
}

09.测试2测试连接

这里看到我们成功的把小白同学查出来了,再同理运行多次查询的测试方法。得到查询耗时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Resource
private StringRedisTemplate stringRedisTemplate;

@Resource
private UserServiceImpl userService;

@Test
void testRedisAndMysql() {
int times = 1;
long start;
long end;
for (int i = 0; i < 6; i++) {
start = System.currentTimeMillis();
for (int j = 0; j < times; j++) {
userService.query().eq("id",1).count();
}
end = System.currentTimeMillis();
System.out.println(times + "次 \t查询mysql数据库耗时" + (end - start) + "ms");
start = System.currentTimeMillis();
for (int j = 0; j < times; j++) {
stringRedisTemplate.opsForValue().get("user");
}
end = System.currentTimeMillis();
System.out.println(times + "次 \t查询redis数据库耗时" + (end - start) + "ms");
times = times * 10;
}
}

10.第二次比较结果.png

11.01第二次比较结果柱状图.png

11.02第二次比较结果柱状图.png

这里我们可以看出,抛出了虚拟机和本地环境的影响之后,redis确实能比mysql快​上一些。但是效果并不是很明显,这与初学redis的我起初认为redis会比mysql快上数倍甚至数十倍的想法大相径庭。毕竟第一印象就是redis是基于内存的,mysql却是基于硬盘的(而且我的mysql和虚拟机均安装在机械硬盘上,不知如果安装在固态上,能否加速)

当然,这里测试的情况过于单一,只是单用户单线程多次查询。

如果是单线程多次修改呢?如果是多线程查询呢​?后面我会再进行进一步的测试,来对比redis和mysql的运行效果。

mysql图标

redis图片