Jmeter性能测试与SQL优化——电影收藏清单小程序获取收藏列表

Jmeter性能测试与SQL优化——电影收藏清单小程序获取收藏列表

JMeter性能测试与SQL优化完整步骤指南

一、准备工作

1.1 确认后端服务运行

1.2测试环境隔离
1.2.1使用本地数据库——创建测试数据库

-- 创建测试数据库

CREATE DATABASE IF NOT EXISTS movie_collection_test

CHARACTER SET utf8mb4

COLLATE utf8mb4_unicode_ci;

-- 使用测试库

USE movie_collection_test;

-- 导入生产表结构(只导结构,不导数据)

-- 方式1:从原库复制表结构

CREATE TABLE users LIKE movie_collection.users;

CREATE TABLE favorite_movies LIKE movie_collection.favorite_movies;

CREATE TABLE watch_plans LIKE movie_collection.watch_plans;

CREATE TABLE verification_codes LIKE movie_collection.verification_codes;

-- 插入测试数据(不要用真实用户数据)

INSERT INTO users (id, phone, password, nickname) VALUES

(1, '13800138000', 'test123', '测试用户1'),

(2, '13800138001', 'test123', '测试用户2');

-- 插入大量测试数据用于压测

DELIMITER $$

CREATE PROCEDURE insert_test_data()

BEGIN

DECLARE i INT DEFAULT 1;

WHILE i <= 5000 DO

INSERT INTO favorite_movies (user_id, movie_name, director, rating, release_date, collection_reason, create_time)

VALUES (1, CONCAT('测试电影', i), '测试导演', ROUND(RAND()*10,1),

DATE_ADD('2020-01-01', INTERVAL FLOOR(RAND()*2000) DAY),

CONCAT('测试收藏理由', i), NOW());

SET i = i + 1;

END WHILE;

END$$

DELIMITER ;

CALL insert_test_data();

-- 验证数据量

SELECT COUNT(*) FROM favorite_movies; -- 应有5000条

修改后端配置连接测试库

创建 .env.test 文件:

# server/.env.test

PORT=3001

DB_HOST=localhost

DB_USER=root

DB_PASSWORD=root

DB_NAME=movie_collection_test

JWT_SECRET=test_secret_key_2026

修改server.js内容,将读取文件改为.env.test

或者直接修改原有的.env文件,将连接的数据库改为movie_collection_test,其他可不做修改即可。

1.2.2使用Docker容器隔离

安装Docker :

通过启用或关闭windows功能打开虚拟机平台和适用于Linux的Windows子系统(WSL)

在终端中输入:wsl –set-default-version 2

Wsl –update –web-download

安装Docker Desktop for Windows

访问 https://www.docker.com/products/docker-desktop/

下载 Docker Desktop for Windows

安装(需要开启Hyper-V或WSL2)

启动Docker Desktop

输入docker -v出现版本号即成功了。使用docker时后端要挂着Docker Desktop

创建测试数据库容器

# 拉取MySQL镜像

docker pull mysql:8.0

# 创建测试数据库容器(端口映射到3307)

docker run -d \

--name movie_collection_test_db \

-p 3307:3306 \

-e MYSQL_ROOT_PASSWORD=root \

-e MYSQL_DATABASE=movie_collection_test \

mysql:8.0 \

--character-set-server=utf8mb4 \

--collation-server=utf8mb4_unicode_ci

参数

作用

docker run -d

后台运行容器(-d = detached,分离模式),不占用终端

--name movie_collection_test_db

给容器命名为 movie_collection_test_db,方便后续管理

-p 3307:3306

端口映射:主机的 3307 端口 → 容器的 3306 端口(MySQL 默认端口)

-e MYSQL_ROOT_PASSWORD=root

设置 MySQL root 用户密码为 root(环境变量)

-e MYSQL_DATABASE=movie_collection_test

容器启动时自动创建名为 movie_collection_test 的数据库

mysql:8.0

使用官方 MySQL 8.0 版本镜像

--character-set-server=utf8mb4

设置服务器默认字符集为 utf8mb4(支持 emoji、全语种,最佳实践)

--collation-server=utf8mb4_unicode_ci

设置排序规则,支持通用 Unicode 排序

连接测试数据库

# 进入容器

docker exec -it movie_collection_test_db mysql -uroot -proot

# 或通过Navicat连接

# 主机:127.0.0.1

# 端口:3307

# 用户名:root

# 密码:1234

问:你的性能测试是怎么隔离环境的?

你:我使用的是Docker容器隔离。在本地用Docker创建了一个独立的MySQL测试容器,映射到3307端口,数据库名也用movie_collection_test区分。这样无论怎么压测,都不会影响真实环境。这种方式的好处是环境干净、可重复、而且用完可以直接销毁容器,非常适合做性能测试。

二、使用JMeter进行压测

2.1 下载并安装JMeter

访问 https://jmeter.apache.org/download_jmeter.cgi

下载 apache-jmeter-5.6.3.zip

解压到任意目录(如 D:\jmeter)

进入 bin 目录,双击 jmeter.bat 启动

2.2 创建测试计划

步骤:

右键点击 测试计划 → 添加 → 线程(用户) → 线程组

线程组配置

参数

说明

线程数

50

模拟50个并发用户

Ramp-Up时间

5

5秒内启动所有线程

循环次数

10

每个用户执行10次请求

总请求数

50 × 10 = 500

共500个请求

2.3 添加HTTP请求

步骤:

右键点击 线程组 → 添加 → 取样器 → HTTP 请求

配置如下:

参数

协议

http

服务器名称或IP

127.0.0.1

端口号

3000

方法

GET

路径

/api/favorite/list

2.4 添加HTTP Header Manager(添加认证Token)

步骤:

右键点击 HTTP请求 → 添加 → 配置元件 → HTTP信息头管理器

添加Header:

名称 值

Authorization Bearer <你的登录token>

如何获取token:

1、先用Postman登录,复制返回的token

2、在Jmeter中自动关联Token

整体流程图

步骤1:

添加登录请求

右键点击线程组 → 添加 → 取样器 → HTTP请求

配置登录请求:

参数

名称

01-登录获取Token

协议

http

服务器

127.0.0.1

端口

3000

方法

POST

路径

/api/login

Body

{"phone":"13800138000","loginType":"password","password":"xiaoming123"}

注:可以添加一个HTTP请求默认值,这样每次写接口的时候不用重复写协议、IP、端口号。

步骤2:添加HTTP 信息头管理器

右键登录请求 → 添加 → 配置元件 → HTTP 信息头管理器

添加 1 行:

名称:Content-Type

值:application/json

步骤3:添加JSON提取器提取Token

右键点击登录请求 → 添加 → 后置处理器 → JSON提取器

参数

名称

token

JSON表达式

$.data.token

匹配编号

1

变量名

token

注:

$.data.token 表示从响应JSON中提取data.token的值

变量名token会存储提取的值,后续用${token}引用

原线程(HTTP请求)中添加请求头

先设置线程数为1测试一次,查看结果树通过:

2.5 添加监听器(查看结果)

步骤:

右键点击 线程组 → 添加 → 监听器 → 查看结果树(查看每个请求详情)

右键点击 线程组 → 添加 → 监听器 → 聚合报告(查看汇总统计)

2.6 运行测试

点击绿色▶️按钮启动测试

等待测试完成(约10-20秒)

2.7 查看聚合和汇总报告

指标

含义

优化前预期值

Average

平均响应时间

约1200ms

Min

最小响应时间

约800ms

Max

最大响应时间

约2000ms

Throughput

吞吐量(QPS)

约40-50

三、定位慢SQL

3.1 开启MySQL慢查询日志

方法一:临时开启(重启失效)

-- 查看当前慢查询状态

SHOW VARIABLES LIKE 'slow_query_log%';

SHOW VARIABLES LIKE 'long_query_time';

-- 开启慢查询日志

SET GLOBAL slow_query_log = ON;

-- 设置慢查询阈值(1秒)

SET GLOBAL long_query_time = 1;

-- 设置日志文件路径(Windows)

SET GLOBAL slow_query_log_file = 'D:/application/mysql-9.0.1-winx64/data/slow.log';

3.2 分析慢查询日志

压测后查看慢查询日志,找到收藏列表的SQL:(在我们刚生成的log日志文件中可查看)

找到类似的语句:

# 慢查询日志示例

# Time: 2026-03-27T10:00:00.000000Z

# Query_time: 1.234 Lock_time: 0.001 Rows_sent: 10 Rows_examined: 15000

SELECT * FROM favorite_movies WHERE user_id = 1 ORDER BY create_time DESC LIMIT 10 OFFSET 0;

关键信息:

Rows_examined: 15000 - 扫描了15000行数据

Query_time: 1.234 - 查询耗时1.2秒

3.3 使用EXPLAIN分析SQL

-- 分析SQL执行计划

EXPLAIN SELECT * FROM favorite_movies WHERE user_id = 1 ORDER BY create_time DESC LIMIT 10 OFFSET 0;

EXPLAIN结果解读

字段

说明

type

ALL

全表扫描(性能最差)

possible_keys

NULL

没有可用索引

key

NULL

没有使用索引

rows

15000

扫描了4905行

四、优化SQL(添加索引)

4.1 添加联合索引

-- 添加联合索引(user_id + create_time)

ALTER TABLE favorite_movies ADD INDEX idx_user_create (user_id, create_time);

-- 验证索引是否创建成功

SHOW INDEX FROM favorite_movies WHERE Table = 'favorite_movies';

4.2 再次使用EXPLAIN验证

EXPLAIN SELECT * FROM favorite_movies WHERE user_id = 1 ORDER BY create_time DESC LIMIT 10 OFFSET 0;

优化后的EXPLAIN结果:

字段

说明

type

ref

索引查找(性能好)

possible_keys

idx_user_create

有可用索引

key

idx_user_create

使用了索引

rows

15

只扫描15行(减少1000倍!)

五、再次压测验证

5.1 重新运行JMeter压测

确保已添加索引

重新运行相同的测试计划

查看聚合报告

5.2 对比优化前后数据

指标

优化前

优化后

提升

Average

1200ms

300ms

↓ 75%

Min

800ms

150ms

↓ 81%

Max

2000ms

500ms

↓ 75%

Throughput

45 req/s

180 req/s

↑ 300%

QPS提升:45 → 180,提升了4倍!

六、完整操作命令汇总

-- 1. 查看当前数据量

SELECT COUNT(*) FROM favorite_movies WHERE user_id = 1;

-- 2. 开启慢查询日志(可选)

SET GLOBAL slow_query_log = ON;

SET GLOBAL long_query_time = 1;

-- 3. 分析SQL(优化前)

EXPLAIN SELECT * FROM favorite_movies WHERE user_id = 1 ORDER BY create_time DESC LIMIT 10 OFFSET 0;

-- 4. 添加联合索引

ALTER TABLE favorite_movies ADD INDEX idx_user_create (user_id, create_time);

-- 5. 再次分析SQL(优化后)

EXPLAIN SELECT * FROM favorite_movies WHERE user_id = 1 ORDER BY create_time DESC LIMIT 10 OFFSET 0;

-- 6. 查看索引

SHOW INDEX FROM favorite_movies;

-- 7. 删除测试数据(可选)

DELETE FROM favorite_movies WHERE movie_name LIKE '测试电影%';

七、面试时如何回答这个问题

我用JMeter对收藏列表接口做了压力测试,模拟50个并发用户,每个用户执行10次请求,发现平均响应时间1.2秒,吞吐量只有45 QPS。

然后我开启了MySQL慢查询日志,发现这个查询每次要扫描1万多行数据。用EXPLAIN分析后发现,SQL没有使用索引。

我分析了业务场景,用户查询收藏时总是按用户ID过滤、按时间排序,所以给 user_id 和 create_time 建了联合索引。优化后再次压测,响应时间降到300毫秒,QPS提升到180,提升了4倍。

这个案例让我深刻理解了索引对查询性能的重要性,也学会了用JMeter和慢查询日志定位性能瓶颈的方法。

八、注意事项

事项

说明

测试环境隔离

不要在生产环境做压测!用本地或测试库

数据准备

测试数据量要足够大(至少1000条),否则看不出效果

多次测试

取多次测试的平均值,避免单次偶然性

监控服务器

压测时观察CPU、内存使用情况,避免压垮服务器

最后:下方这份完整的软件测试 视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

​​​件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。