Spring boot + mybatis-plus + Redis 实现数据多级缓存(模拟生产环境)

目录

上期是介绍:

本期目标是:

环境介绍

安装依赖

配置文件

缓存配置类

com/aigouwu/www/entily

com/aigouwu/www/mapper

com/aigouwu/www/service

com/aigouwu/www/service/impl

com/aigouwu/www/controller

启动类添加注解

shopping_system.sql

测试接口

查看缓存命中率

实际性能对比实验


上期是介绍:

揭开AI Agent 的一条数据驱动智能的闭环链路

本期目标是:

利用 spring boot + mybatis-plus 去测试数据响应及缓存

分析出 mybatis的一级缓存,数据库的 InnoDB Buffer Pool 缓存,及redis 缓存

环境介绍

* JDK 17 + Maven 3

* springboot + mybatis-plus + redis

* MySQL8.0(底部附加SQL直接粘贴使用即可)

跳过这些安装的话,可以gitee直接下载 公众号 wmcode 回复 【2000】

安装依赖

在Spring Boot中使用@Cacheable注解需要添加缓存相关的依赖。根据你使用的缓存实现不同,需要的依赖也不同。

复制代码
<dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!-- MySQL -->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <scope>runtime</scope>        </dependency>        <!-- MyBatis Plus -->        <dependency>            <groupId>com.baomidou</groupId>            <artifactId>mybatis-plus-boot-starter</artifactId>            <version>3.5.3.1</version>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-cache</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-redis</artifactId>        </dependency>        <!-- 如果需要JSON序列化 -->        <dependency>            <groupId>com.fasterxml.jackson.datatype</groupId>            <artifactId>jackson-datatype-jsr310</artifactId>        </dependency>    </dependencies>

配置文件

application.properties/yaml 中配置Redis连接

复制代码
# application.ymlserver:  port: 8080spring:  redis:    host: localhost    port: 6379    database: 0    lettuce:      pool:        max-active: 20        max-idle: 10        min-idle: 5        max-wait: 3000ms    cache:      type: redis      redis:        time-to-live: 300s          # 缓存5分钟        cache-null-values: false    # 不缓存null值        key-prefix: "cache:"        # key前缀        use-key-prefix: true  datasource:    hikari:      maximum-pool-size: 100    driver-class-name: com.mysql.cj.jdbc.Driver    url: jdbc:mysql://localhost:3306/shopping_system?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true    username: root    password: 你的数据库密码  jackson:    date-format: yyyy-MM-dd HH:mm:ss    time-zone: GMT+8mybatis-plus:  configuration:    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  global-config:    db-config:      id-type: auto      logic-delete-field: deleted      logic-delete-value: 1      logic-not-delete-value: 0

缓存配置类

(可选,用于自定义配置,上面yaml文件配置了就不用再配置了)

复制代码
@Configuration@EnableCachingpublic class CacheConfig {    @Bean    public CacheManager cacheManager(RedisConnectionFactory factory) {        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()            .entryTtl(Duration.ofMinutes(10))  // 设置缓存过期时间            .disableCachingNullValues();       // 不缓存null值        return RedisCacheManager.builder(factory)            .cacheDefaults(config)            .build();    }}

com/aigouwu/www/entily

复制代码
package com.aigouwu.www.entily;import com.baomidou.mybatisplus.annotation.*;import lombok.Data;import java.io.Serializable;import java.math.BigDecimal;import java.time.LocalDateTime;@Data@TableName("t_item")public class Item implements Serializable {    @TableId(type = IdType.AUTO)    private Long itemId;    private String itemName;    private String itemClass;    private BigDecimal itemMoney;    private Integer itemNumber;    private String itemStatus;    @TableField(fill = FieldFill.INSERT)    private LocalDateTime createTime;    @TableField(fill = FieldFill.INSERT_UPDATE)    private LocalDateTime updateTime;}

com/aigouwu/www/mapper​​​​​​​

复制代码
package com.aigouwu.www.mapper;import com.aigouwu.www.entily.Item;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.apache.ibatis.annotations.Mapper;@Mapperpublic interface ItemMapper extends BaseMapper<Item> {}

com/aigouwu/www/service

package com.aigouwu.www.service;

复制代码
import com.aigouwu.www.entily.Item;import com.baomidou.mybatisplus.core.metadata.IPage;import java.util.List;public interface ItemService {    boolean saveItem(Item item);    boolean updateItem(Item item);    boolean deleteItem(Long itemId);    Item getItemById(Long itemId);    IPage<Item> queryItems(Item item);    List<Item> getOnSaleItems();    List<Item>  getAllItems();}

com/aigouwu/www/service/impl

复制代码
package com.aigouwu.www.service.impl;import com.aigouwu.www.entily.Item;import com.aigouwu.www.mapper.ItemMapper;import com.aigouwu.www.service.ItemService;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Service;import org.springframework.util.StringUtils;import java.util.List;@Service@RequiredArgsConstructorpublic class ItemServiceImpl implements ItemService  {    private final ItemMapper itemMapper;    @Override    public boolean saveItem(Item item) {        // 验证单品名称是否重复        LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(Item::getItemName, item.getItemName());        if (itemMapper.selectCount(queryWrapper) > 0) {            return false;        }        return itemMapper.insert(item) > 0;    }    @Override    public boolean updateItem(Item item) {        // 验证单品是否存在        Item existingItem = itemMapper.selectById(item.getItemId());        if (existingItem == null) {            return false;        }        // 验证名称是否重复(排除自身)        if (item.getItemName().equals(existingItem.getItemName())) {            LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();            queryWrapper.eq(Item::getItemName, item.getItemName());            queryWrapper.ne(Item::getItemId, item.getItemId());            if (itemMapper.selectCount(queryWrapper) > 0) {                return false;            }        }        return itemMapper.updateById(item) > 0;    }    @Override    public boolean deleteItem(Long itemId) {        return itemMapper.deleteById(itemId) > 0;    }    @Override    public Item getItemById(Long itemId) {        return itemMapper.selectById(itemId);    }    @Override    public IPage<Item> queryItems(Item item) {        return doQuery(item);    }    private IPage<Item> doQuery(Item item) {        Page<Item> page = new Page<>(1, 10);          QueryWrapper<Item> wrapper = new QueryWrapper<>();        if (StringUtils.hasText(item.getItemName())) {            wrapper.like("item_name", item.getItemName());        }        if (StringUtils.hasText(item.getItemClass())) {            wrapper.eq("item_class", item.getItemClass());        }        if (StringUtils.hasText(item.getItemStatus())) {            wrapper.eq("item_status", item.getItemStatus());        }        return itemMapper.selectPage(page, wrapper);    }    @Override    public List<Item> getOnSaleItems() {        LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();        queryWrapper.eq(Item::getItemStatus, "ONSALE");        return itemMapper.selectList(queryWrapper);    }    @Override    public List<Item> getAllItems() {        return itemMapper.selectList(null);    }}

com/aigouwu/www/controller

复制代码
package com.aigouwu.www.controller;import com.aigouwu.www.entily.Item;import com.aigouwu.www.service.ItemService;import com.baomidou.mybatisplus.core.metadata.IPage;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;import java.util.List;@RestController@RequestMapping("/api/item")@RequiredArgsConstructor@Slf4jpublic class ItemController {    private final ItemService itemService;    @PostMapping    public boolean saveItem(@RequestBody Item item) {        return itemService.saveItem(item);    }    @PutMapping    public boolean updateItem(@RequestBody Item item) {        return itemService.updateItem(item);    }    @DeleteMapping("/{id}")    public boolean deleteItem(@PathVariable Long id) {        return itemService.deleteItem(id);    }    @GetMapping("/{id}")    public Item getItemById(@PathVariable Long id) {        return itemService.getItemById(id);    }    @PostMapping("/list")    public IPage<Item> queryItems(@RequestBody Item item) {        return itemService.queryItems(item);    }    @GetMapping("/onsale")    public List<Item> getOnSaleItems() {        return itemService.getOnSaleItems();    }    @GetMapping("/list/all")    public List<Item> getAllItems() {        return itemService.getAllItems();    }}

启动类添加注解

添加@EnableCaching注解

复制代码
@SpringBootApplication

@EnableCaching
@MapperScan("com.aigouwu.www.mapper")
publicclassCacheSpringAdminDemoOneApplication {
publicstaticvoidmain(String[] args) {
SpringApplication.run(CacheSpringAdminDemoOneApplication.class, args);
    }
}

shopping_system.sql

复制代码
/*
 Navicat Premium Data Transfer
 Source Server         : mysql80
 Source Server Type    : MySQL
 Source Server Version : 80033
 Source Host           : localhost:3306
 Source Schema         : shopping_system
 Target Server Type    : MySQL
 Target Server Version : 80033
 File Encoding         : 65001
 Date: 29/12/2025 08:47:48
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_group_item_relation
-- ----------------------------
DROP TABLE IF EXISTS `t_group_item_relation`;
CREATE TABLE `t_group_item_relation`  (
  `relation_id` bigint NOT NULL AUTO_INCREMENT COMMENT '关联ID',
  `item_group_id` bigint NOT NULL COMMENT '组合ID',
  `item_id` bigint NOT NULL COMMENT '单品ID',
  `item_count` int NOT NULL DEFAULT 1 COMMENT '单品数量',
  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`relation_id`) USING BTREE,
  UNIQUE INDEX `uk_group_item`(`item_group_id` ASC, `item_id` ASC) USING BTREE,
  INDEX `idx_group_id`(`item_group_id` ASC) USING BTREE,
  INDEX `idx_item_id`(`item_id` ASC) USING BTREE,
  CONSTRAINT `t_group_item_relation_ibfk_1` FOREIGN KEY (`item_group_id`) REFERENCES `t_item_group` (`item_group_id`) ON DELETE CASCADE ON UPDATE RESTRICT,
  CONSTRAINT `t_group_item_relation_ibfk_2` FOREIGN KEY (`item_id`) REFERENCES `t_item` (`item_id`) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '组合-单品关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of t_group_item_relation
-- ----------------------------
INSERT INTO `t_group_item_relation` VALUES (4, 1, 8, 1, '2025-12-22 12:47:20');
INSERT INTO `t_group_item_relation` VALUES (7, 1, 4, 2, '2025-12-22 12:47:20');
INSERT INTO `t_group_item_relation` VALUES (15, 4, 6, 3, '2025-12-22 13:35:42');
INSERT INTO `t_group_item_relation` VALUES (16, 4, 4, 2, '2025-12-22 13:35:42');
INSERT INTO `t_group_item_relation` VALUES (17, 4, 5, 1, '2025-12-22 13:35:42');
-- ----------------------------
-- Table structure for t_item
-- ----------------------------
DROP TABLE IF EXISTS `t_item`;
CREATE TABLE `t_item`  (
  `item_id` bigint NOT NULL AUTO_INCREMENT COMMENT '单品ID',
  `item_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '单品名称',
  `item_class` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分类(DAILY-日化, FOOD-食品, HOME-家居)',
  `item_money` decimal(10, 2) NOT NULL COMMENT '单价',
  `item_number` int NOT NULL DEFAULT 0 COMMENT '库存数量',
  `item_status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'ONSALE' COMMENT '状态(ONSALE-在售, OFFSALE-下架)',
  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`item_id`) USING BTREE,
  INDEX `idx_name`(`item_name` ASC) USING BTREE,
  INDEX `idx_class`(`item_class` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '单品表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of t_item
-- ----------------------------
INSERT INTO `t_item` VALUES (1, '洗发水', 'DAILY', 99.00, 120, 'ONSALE', '2025-12-20 10:58:17', '2025-12-22 11:28:58');
INSERT INTO `t_item` VALUES (2, '沐浴露', 'DAILY', 28.00, 80, 'ONSALE', '2025-12-20 10:58:17', '2025-12-20 10:58:17');
INSERT INTO `t_item` VALUES (3, '薯片', 'FOOD', 8.50, 200, 'ONSALE', '2025-12-20 10:58:17', '2025-12-20 10:58:17');
INSERT INTO `t_item` VALUES (4, '毛巾', 'HOME', 15.00, 150, 'ONSALE', '2025-12-20 10:58:17', '2025-12-20 10:58:17');
INSERT INTO `t_item` VALUES (5, '牙膏', 'DAILY', 12.00, 120, 'ONSALE', '2025-12-20 10:58:17', '2025-12-20 10:58:17');
INSERT INTO `t_item` VALUES (6, '可乐', 'FOOD', 3.50, 300, 'ONSALE', '2025-12-20 10:58:17', '2025-12-20 10:58:17');
INSERT INTO `t_item` VALUES (7, '洗衣液', 'HOME', 45.00, 60, 'ONSALE', '2025-12-20 10:58:17', '2025-12-20 10:58:17');
INSERT INTO `t_item` VALUES (8, '小猪饼干', 'FOOD', 1.80, 100, 'ONSALE', '2025-12-20 11:18:06', '2025-12-20 11:18:06');
INSERT INTO `t_item` VALUES (9, '苏打水', 'FOOD', 1.50, 188, 'ONSALE', '2025-12-22 12:16:03', '2025-12-22 12:16:03');
-- ----------------------------
-- Table structure for t_item_group
-- ----------------------------
DROP TABLE IF EXISTS `t_item_group`;
CREATE TABLE `t_item_group`  (
  `item_group_id` bigint NOT NULL AUTO_INCREMENT COMMENT '组合ID',
  `item_group_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '组合名称',
  `item_group_money` decimal(10, 2) NULL DEFAULT NULL COMMENT '组合总价',
  `item_group_number` int NULL DEFAULT 0 COMMENT '组合库存',
  `item_group_status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT 'ONSALE' COMMENT '状态(ONSALE-上架, OFFSALE-下架)',
  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`item_group_id`) USING BTREE,
  INDEX `idx_status`(`item_group_status` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '商品组合表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of t_item_group
-- ----------------------------
INSERT INTO `t_item_group` VALUES (1, '洗护组合', 31.80, 75, 'ONSALE', '2025-12-21 12:37:26', '2025-12-21 12:37:26');
INSERT INTO `t_item_group` VALUES (4, '111', 52.50, 75, 'ONSALE', '2025-12-22 13:34:09', '2025-12-22 13:34:09');
-- ----------------------------
-- Table structure for t_package
-- ----------------------------
DROP TABLE IF EXISTS `t_package`;
CREATE TABLE `t_package`  (
  `package_id` bigint NOT NULL AUTO_INCREMENT COMMENT '套餐ID',
  `package_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '套餐名称',
  `item_group_id` bigint NOT NULL COMMENT '关联的组合ID',
  `package_price` decimal(10, 2) NOT NULL COMMENT '套餐售价',
  `package_stock` int NOT NULL DEFAULT 0 COMMENT '套餐库存',
  `package_status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'ONSALE' COMMENT '状态(ONSALE-上架, OFFSALE-下架)',
  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`package_id`) USING BTREE,
  INDEX `idx_group_id`(`item_group_id` ASC) USING BTREE,
  INDEX `idx_status`(`package_status` ASC) USING BTREE,
  CONSTRAINT `t_package_ibfk_1` FOREIGN KEY (`item_group_id`) REFERENCES `t_item_group` (`item_group_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '套餐表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of t_package
-- ----------------------------
INSERT INTO `t_package` VALUES (1, '家庭洗护套餐', 1, 29.00, 40, 'ONSALE', '2025-12-21 13:17:55', '2025-12-21 13:17:55');
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
  `user_password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
  `user_role` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色(ADMIN-商家管理员, CONSUMER-消费者)',
  `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`user_id`) USING BTREE,
  UNIQUE INDEX `user_name`(`user_name` ASC) USING BTREE,
  INDEX `idx_username`(`user_name` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'admin', '123456', 'ADMIN', '2025-12-20 10:58:17', '2025-12-22 12:32:31');
INSERT INTO `t_user` VALUES (2, 'user', '123456', 'CONSUMER', '2025-12-20 10:58:17', '2025-12-22 12:32:35');
INSERT INTO `t_user` VALUES (3, '13800138000', '123456', 'CONSUMER', '2025-12-20 10:58:17', '2025-12-22 12:32:31');
SET FOREIGN_KEY_CHECKS = 1;

基础环境终于搞定了!!!

那么接下来开始正事了

服务开启来后

测试接口

对获取指定商品接口为例

312ms~580ms 还是太慢了

先搞个日志

复制代码
@Slf4j

然后去搞个缓存+日志

复制代码
    @Override    @Cacheable(value = "items", key = "#itemId", unless = "#result == null")    public Item getItemById(Long itemId) {        log.info("缓存未命中,执行数据库查询: {}", itemId);        return itemMapper.selectById(itemId);    }

按道理应该第一次就会312ms ~ 600ms 左右,后面加上缓存就会 <10ms

第一次请求(确实未命中缓存,但是 去查询了并写入了缓存)

去redis 客户端去看看

第二次请求

5ms!!!

那么换另一个商品试试看呢?

第一次查询 就13ms,什么原因呢?其实是因为有mybatis-plus 的一级缓存及数据库的缓存,所以才这么快

禁用 mybatis-plus的一级缓存

复制代码
local-cache-scope: statement # 关闭一级缓存

把redis缓存注释掉

并且删掉redis缓存数据

重启application项目!

接口测试!

第一次测试 279ms

第二次测试 7ms

我推测应该走了数据库缓存(无奈)

先不管了,先去处理缓存问题,只要走缓存那么就不会走到数据库

解开缓存注释

重启application项目!

测试请求接口!

第一次 614ms

确实未命中

查看 redis 是否写入了数据

确实写了

第二次 7ms

命中缓存

第三次 4ms

同样命中缓存

换其他商品测试

第一次测试 9ms

没命中缓存,但也能快速获取到,是怎么做到的呢?

推测应该是数据库缓存了

于是我查询了一下

8.0的已经去除了

复制代码
SHOW VARIABLES LIKE 'query_cache%';

InnoDB Buffer Pool(最重要的缓存)

它缓存的是数据和索引的页​​​​​​​

复制代码
-- 查看Buffer Pool状态
SHOW VARIABLES LIKE 'innodb_buffer_pool%';
SHOW ENGINE INNODB STATUS\G
-- 通常设置为物理内存的70-80%
-- innodb_buffer_pool_size = 2G 或更大

工作原理

  • 第一次查询:从磁盘读取数据页 → 存入Buffer Pool → 返回结果

  • 第二次查询:直接**从内存(Buffer Pool)**读取 → 返回结果(这就是为什么这么快)

刚刚的场景分析

  • 第一次:磁盘 → Buffer Pool(稍慢,可能20-30ms)

  • 第二次及以后:Buffer Pool内存读取(<5ms)

查看缓存命中率

实际性能对比实验

复制代码
-- 实验1:清空Buffer Pool(生产环境不要执行!)
-- 重启MySQL服务或执行:
SET GLOBAL innodb_buffer_pool_dump_now = ON;
SET GLOBAL innodb_buffer_pool_load_now = OFF;
-- 第一次查询(冷启动)
SELECT * FROM large_table WHERE id = 1;  -- 可能100ms+
-- 第二次查询(热数据)
SELECT * FROM large_table WHERE id = 1;  -- <10ms
-- 实验2:强制从磁盘读取
SELECT SQL_NO_CACHE * FROM table;  -- 在8.0中已无效,只是习惯写法

那么就到这里了~

测试SQL(自取)

复制代码
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'innodb_log_file_size'; 
-- 查看InnoDB缓存命中率
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
/*
Innodb_buffer_pool_read_requests      # 总的读取请求数
Innodb_buffer_pool_reads              # 从磁盘读取的次数
*/
-- 命中率 = 1 - (reads/requests) 
-- 如果接近99%,说明几乎所有数据都在内存中
SHOW VARIABLES LIKE 'query_cache%';
-- 查看Buffer Pool状态
SHOW VARIABLES LIKE 'innodb_buffer_pool%';
SHOW ENGINE INNODB STATUS\G
-- 通常设置为物理内存的70-80%
-- innodb_buffer_pool_size = 2G 或更大

下期的内容更精彩,期待一下吧!!


* Thanks you *

如果觉得文章内容不错,随手帮忙点个赞在看转发一下,如果想第一时间收到推送,也可以给我个星标⭐~谢谢你看我的文章。


*Spring 系列 - 往期推荐 *

如何快速起 Spring Ai Alibaba 的智能记忆会话的业务项目(零基础学习Ai-第一期)(推荐)****

利用Reids记忆存储(高并发),持久化记忆会话的基础业务功能(零基础学习Ai-第二期)

构建 Tools 达成智能化的会话的基础业务功能(零基础学习Ai-第三期)

Springboot单体架构下如何做 远程调用 (源码)

SpringBoot整合Openfeign接入Kimi Ai!!超简单,居然没多少行代码??(附加兜底教程)

SpringBoot接入Kimi实践记录轻松上手(推荐)

Spring Ai | 极简代码从零带你一起走进AI项目(中英)

Swagger | 手把手带你写自动生成接口文档的爽感(零基础亲测实用)

Mongodb | 基于Springboot开发综合社交网络应用的项目案例(中英)

Open Ai | 从零搭建属于你的Ai项目(中英结合)

MongoDB | 零基础学习与Springboot整合ODM实现增删改查(附源码)(推荐)********

Openfeign | 只传递城市代码,即可获取该地域实时的天气数据(免费的天气API)


*前后端 系列 - 往期推荐 *

彻底解决不同架构前后端分离项目的跨域问题(强烈推荐)

Vue 项目打包部署还存在问题?你知道怎么做吧?

Maven | 站在初学者的角度配置与项目创建(新手必学会)


*其他 系列 - 往期推荐 *

实现如何利用 Kafka 延时删除 用户邮箱的验证码(如何发送邮箱+源码) - 第一期

Docker小白入门教程一篇领你入门(CRUD全命令+无废话版+问题集)

想要高效处理,那不妨看看 Python的 异步 Asyncio 保证效率翻多倍

银河麒麟 | ubuntu 安装国产达梦DM8数据库(安装+外网通+IDEA连接)

国产操作系统-银河麒麟本地化部署Ollama国产开源的AI大模型Qwen3

Linux | 零基础Ubuntu搭建JDK

Redis | 缓存技术对后端的重要性,你知道多少?


感谢阅读 | 更多内容尽在公棕号 WMCode | CSDN**@小Mie不吃饭**

©著作权归作者所有,转载或内容合作请联系作者,谢谢支持与配合

相关推荐
盒马coding2 小时前
高性能MySQL到PostgreSQL异构数据库转换工具MySQL2PG
数据库·mysql·postgresql
不思念一个荒废的名字2 小时前
【黑马JavaWeb+AI知识梳理】Web后端开发08 - 总结
java·后端
heartbeat..2 小时前
Java IO 流完整解析:原理、分类、使用规范与最佳实践
java·开发语言·io·文件
Justin_192 小时前
k8s常见问题(3)
java·开发语言
Knight_AL2 小时前
Java 内存溢出(OOM)排查实战指南:从复现到 MAT Dump 分析
java·开发语言
糯诺诺米团2 小时前
C++多线程打包成so给JAVA后端(Ubuntu)<1>
java·开发语言
刘宇涵492 小时前
递归Java
java
代码不停2 小时前
Spring Boot快速入手
java·spring boot·后端
-Excalibur-2 小时前
关于计算机网络当中的各种计时器
java·c语言·网络·c++·笔记·python·计算机网络