性能分析之MySQL索引实战案例

2024-09-09 17:44

本文主要是介绍性能分析之MySQL索引实战案例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、前言
  • 二、准备
  • 三、MySQL索引优化
  • 四、MySQL 索引知识回顾
  • 五、总结

一、前言

在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引?

  • 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP

二、准备

打开IDEA找到登录请求资源路径位置,代码如:

@PostMapping(value = "/login")
public BaseResponseInfo login(@RequestParam(value = "loginName", required = false) String loginName,@RequestParam(value = "password", required = false) String password,HttpServletRequest request)throws Exception {

**步骤1:**找到登录 Controller 调 service 位置
在这里插入图片描述

**步骤2:**找到方法实现层:
在这里插入图片描述
解释:
从上面代码可以看出,用户登录传入用户名密码,代码根据用户去DAO层去查询是否有该用户;
在这里插入图片描述
说明:Dao层就是常规写法,没有什么特别地方,再跳转xml文件查看SQL是怎么写的:
在这里插入图片描述

说明:根据条件查询全部数据,既然这是登录接口传入的是用户名,那么应该在用户名处增加用户索引,这样查询能加快速度;

索引类似于字典目录,通过索引能快速找到响应数据;

在这里插入图片描述
解释:
如果查询为空或者查询结果为0表示数据库么有数据直接返回用户不存在,如果存在在往下走走;
在这里插入图片描述
解释:
如果上面都通过,这里又根据用户名密码查询数据库,这里作者为什么要查询两次数据库,既然上面已经查询完全可以在内存做判断;假如数据库有1000千用户数,每个用户登录都需要查询两次数据,也是一笔不小的开支;

三、MySQL索引优化

上面已经发现索引有问题,但是发现用户表数据很少,第一步先增加用户数据,再通过JMeter进行压测,造数据在性能测试中是常见的事件,这次造数据直接通过 java for 循环造数据,代码参考如下:


/*** @description: 注册用户* @author: 李文* @create: 2021-03-19 21:03**/
@RunWith(SpringRunner.class)
@SpringBootTest
public class LoginRegTest {@Resourceprivate UserMapper userMapper;@Testpublic void contextLoads() {try {for (int j = 0; j < 100; j++) {for (int i = 0; i < 1000; i++) {UserEx userEx = new UserEx();userEx.setLoginName(RandomUtil.randomString(10));userEx.setUsername(RandomUtil.randomString(8));userEx.setEmail(RandomUtil.randomInt(1, 1100) + "@7DGroup.com");userEx.setPassword(Tools.md5Encryp(BusinessConstants.USER_DEFAULT_PASSWORD));userEx.setIsystem(BusinessConstants.USER_NOT_SYSTEM);userEx.setIsmanager(BusinessConstants.USER_NOT_MANAGER);userEx.setStatus(BusinessConstants.USER_STATUS_NORMAL);userMapper.insert(userEx);}}} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}
}

再次打开MySQL客户端输入如下SQL语句:

mysql> SELECT count(*) from `jsh_user`;
+----------+
| count(*) |
+----------+
| 333724   |
+----------+
1 行于数据集 (0.07)mysql> SELECT count(*) from `jsh_user`;EXPLAIN SELECT id,username,login_name, PASSWORD,position, department, email, phonenum, ismanager, isystem, STATUS, description, remark, tenant_id
FROMjsh_user
WHERE(login_name = "admin"AND PASSWORD = "e10adc3949ba59abbe56e057f20f883e"AND STATUS = 0);
+----------+
| count(*) |
+----------+
| 333724   |
+----------+
1 行于数据集 (0.05)+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1  | SIMPLE      | jsh_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 331551 | 0.10     | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+--------+----------+-------------+
1 行于数据集 (0.06)mysql> 

截图如下:
在这里插入图片描述
为了减少性能消耗,这次都采用后台运行,把项目跑起来显示如下:
在这里插入图片描述
JMeter运行结果如下:
在这里插入图片描述

liwen@liwen123 hunhe % jmeter -n -t he1.jmx
Creating summariser <summary>
Created the tree successfully using he1.jmx
Starting standalone test @ Fri Mar 19 22:01:53 CST 2021 (1616162513949)
Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445
summary +     44 in 00:00:06 =    7.8/s Avg:   534 Min:   472 Max:   910 Err:     0 (0.00%) Active: 9 Started: 9 Finished: 0
summary +    336 in 00:00:30 =   11.2/s Avg:  2129 Min:   537 Max:  3626 Err:     0 (0.00%) Active: 30 Started: 30 Finished: 0
summary =    380 in 00:00:36 =   10.7/s Avg:  1944 Min:   472 Max:  3626 Err:     0 (0.00%)

运行几分钟结果如下:
在这里插入图片描述
MySQL增加索引语句:

ALTER TABLE `jsh_user` ADD INDEX index_name ( `login_name` )

增加索引结果如下:

在这里插入图片描述
调优结果:

在这里插入图片描述
JMeter后台数据如下:

在这里插入图片描述
说明:
通过直接增加索引TPS明显增加;

四、MySQL 索引知识回顾

MySQL索引分为:
(1)主键索引 PRIMARY KEY:它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引。
(2) 唯一索引 UNIQUE:

ALTER TABLE table_name ADD UNIQUE (column)

(3) 普通索引 INDEX

ALTER TABLE table_name ADD INDEX index_name (column)

(4) 组合索引 INDEX

ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3)

(5) 全文索引 FULLTEXT

ALTER TABLE table_name ADD FULLTEXT (column)

查看索引:

mysql> show index from  jsh_user;
+----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| Table    | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| jsh_user | 0          | PRIMARY    | 1            | id          | A         | 3           | NULL     | NULL   |      | BTREE      |         |               | YES     |
| jsh_user | 1          | index_name | 1            | login_name  | A         | 331551      | NULL     | NULL   |      | BTREE      |         |               | YES     |
+----------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
2 行于数据集 (0.02)mysql>

删除索引:

ALTER TABLE  jsh_user DROP INDEX  index_name;

更多MySQL性能分析请参考《性能测试实战30讲》中的:

  • 《22丨MySQL:数据库级监控及常用计数器解析(上)》
  • 《23丨MySQL:数据库级监控及常用计数器解析(下)》

五、总结

性能优化是一个反复验证尝试的过程,但调优步骤是有逻辑。在这一节中通过观察代码步骤来跟踪并理解为什么在用户名上面增加索引,通过边压测边增加索引看到调优结果。

相关系列:

  • 性能工具之 JMeter ajax 简单登录案例实战
  • 性能工具之 JProfiler 简单登录案例分析实战

这篇关于性能分析之MySQL索引实战案例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1151846

相关文章

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

MySQL 衍生表(Derived Tables)的使用

《MySQL衍生表(DerivedTables)的使用》本文主要介绍了MySQL衍生表(DerivedTables)的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学... 目录一、衍生表简介1.1 衍生表基本用法1.2 自定义列名1.3 衍生表的局限在SQL的查询语句select

MySQL 横向衍生表(Lateral Derived Tables)的实现

《MySQL横向衍生表(LateralDerivedTables)的实现》横向衍生表适用于在需要通过子查询获取中间结果集的场景,相对于普通衍生表,横向衍生表可以引用在其之前出现过的表名,本文就来... 目录一、横向衍生表用法示例1.1 用法示例1.2 使用建议前面我们介绍过mysql中的衍生表(From子句

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

六个案例搞懂mysql间隙锁

《六个案例搞懂mysql间隙锁》MySQL中的间隙是指索引中两个索引键之间的空间,间隙锁用于防止范围查询期间的幻读,本文主要介绍了六个案例搞懂mysql间隙锁,具有一定的参考价值,感兴趣的可以了解一下... 目录概念解释间隙锁详解间隙锁触发条件间隙锁加锁规则案例演示案例一:唯一索引等值锁定存在的数据案例二:

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA