数据量较小的表是否有必要添加索引问题分析

目录

    • 前言
    • 一、分析前准备
      • 1.1、准备测试表和数据
      • 1.2、插入测试数据
      • 1.3、测试环境说明
    • 二、具体业务分析
      • 2.1、单次查询耗时分析
      • 2.2、无索引并发查询服务器CPU占用率分析
      • 2.3、添加索引并发查询服务器CPU占用率分析
    • 三、总结

前言

      在一次节日活动我们系统访问量到达了平时的两倍,我们线上高峰期数据库CPU使用率从平常的20%左右飙升到了65%左右,数据库用的是阿里云的RDS-MySQL配置是32核 128G,并且为了应对活动我们还开启了SQL洞察(用于分析SQL的执行时间、次数、耗时比等),通过耗时比例能找到一个SQL占用整体耗时比例极高,并且执行次数比例不高,数据扫描行挺高的接近40w,查询调整是没有索引的,但是平均查询耗时在230ms并没有触发我们的慢SQL阈值,从平均查询耗时来看好像没什么问题,但是如果这张表是一张访问频率很高的表,那么问题就大了,最开始这张表预计存储数据量在1k左右,因为后面业务发展表的数据量有所增长,虽然单次查询耗时不高,但是扫描行很高导致CPU使用率飙升,下面开始对数据量很小的表是否有必要添加索引问题分析。

一、分析前准备

1.1、准备测试表和数据

    这里准备一个门店信息表。

CREATE TABLE `shop_info` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '门店ID',`origin_id` varchar(100) DEFAULT NULL COMMENT '门店唯一编号',`phone` varchar(100) DEFAULT NULL COMMENT '手机号',`location` varchar(100) DEFAULT NULL COMMENT '门店经纬度',`city_info` varchar(100) DEFAULT NULL COMMENT '城市信息',`create_time` bigint(20) DEFAULT NULL COMMENT '创建日期',`update_time` bigint(20) DEFAULT NULL COMMENT '更新日期',PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='门店信息表';

1.2、插入测试数据

    我这里在表里面插入了1000条数据用于测试,我这里用的MyBatis-Plus只提供核心业务插入代码,有需要自己插入即可。

    public void batchInsert(int num) {ArrayList<ShopInfo> shopInfos = new ArrayList<>();for (int i = 0; i < num; i++) {ShopInfo shopInfo = new ShopInfo();shopInfo.setOriginId(RandomUtil.randomString(20));shopInfo.setPhone("186"+RandomUtil.randomNumbers(8));shopInfo.setLocation("114."+RandomUtil.randomNumbers(6)+","+"23."+RandomUtil.randomNumbers(6));shopInfo.setCityInfo("xxx");long time = System.currentTimeMillis();shopInfo.setCreateTime(time);shopInfo.setUpdateTime(time);shopInfos.add(shopInfo);}this.saveBatch(shopInfos);}

1.3、测试环境说明

  • 服务器:阿里云CentOS7 2核4G
  • 数据库:MySQL8.0
  • 测试客户端:SpringBoot + MyBatis-Plus + druid

这里测试时我是通过本地直接连接云服务进行的测试,部分耗时可能会高一点。

二、具体业务分析

2.1、单次查询耗时分析

    这里我进行了多次查询,每次查询基本上都在0.13s左右,查询响应时间还能接受。

SELECT * FROM shop_info WHERE origin_id = "trj3arga4b5xsf4c5ie7";

在这里插入图片描述

2.2、无索引并发查询服务器CPU占用率分析

  • 1、通过top -p pid可以看到当前MySQL占用CPU为0

在这里插入图片描述

  • 2、并发查询测试,这里线程池核心线程数为100,数据源的最大连接数设置的也为100
    @Testpublic void t1() throws InterruptedException {// 查询出所有的门店数据用于测试查询List<ShopInfo> list = shopInfoService.list();List<String> originIdList = list.stream().map(ShopInfo::getOriginId).collect(Collectors.toList());long startTime = System.currentTimeMillis();// 开始时间戳ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 100, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());int num = 10000;CountDownLatch countDownLatch = new CountDownLatch(num);for (int i = 0; i <num; i++) {executor.execute(()->{ShopInfo shopInfo = shopInfoService.selectByOriginId(originIdList.get(RandomUtil.randomInt(originIdList.size() - 1)));log.info("shopInfo:{}",shopInfo);countDownLatch.countDown();});}countDownLatch.await();executor.shutdown();long endTime = System.currentTimeMillis();// 结束时间戳log.info("查询耗时:{}",endTime - startTime);}
2024-05-23 18:19:25.747 |  INFO [            main] com.kerwin.dbshop.ShopInfoTest   63 -| 查询耗时:8669

这里10000次查询耗时8669毫秒。

  • 3、查询时MySQL占用CPU峰值达到了90%多

在这里插入图片描述

2.3、添加索引并发查询服务器CPU占用率分析

    这里给origin_id字段添加一个普通索引。

ALTER TABLE `shop_info` ADD INDEX `idx_origin_id`(`origin_id`);
  • 1、添加索引后单次查询耗时在0.117s的样子,比不加索引只快了一点,因为数据量比较少单次查询耗时不明显。

在这里插入图片描述

  • 2、并发查询测试,测试代码和之前一样
2024-05-23 18:30:59.734 |  INFO [            main] com.kerwin.dbshop.ShopInfoTest  63 -| 查询耗时:7754

这里不加索引和加索引并发查询耗时其实区别不大,因为数据量比较少,而且MySQL也会将读取出来的数据进行缓存处理,走索引快速定位某一行和全表扫描在我这个测试程序下查询耗时区别很小。

  • 3、查询时MySQL占用CPU峰值只有32.3%,相比于不加索引CPU使用率降低了非常多。
    在这里插入图片描述

三、总结

  • 通过上面不太全面的分析,大致可以得出一个结论,被频繁访问的小表如果没有索引,那么高并发查询时CPU使用率会非常高,添加上对应查询索引后CPU使用率下降了非常多。

  • 当然并不是所有小表都适合或者说有必要加索引,比如表数据非常少,预计最多几十条添不添加其实没什么差别,就算全表扫描和走索引区别也不大,可以加但是没太大必要,索引查询后还需要根据数据ID进行回表查询,MySQL优化器可能会选择直接进行全表扫描,还有一些情况其实不适合添加索引,比如查询字段为大量重复数据的列,比如状态字段(启用、停用),这种类型的字段区分度不高不适合作为查询的索引,不过也要分业务,在某些时候可能的确需要。

  • 再换个思路,一般什么样的表数据量会比较少?一般都是一些配置表、方案表等,而这些类型的表都有一个特点,数据变化不频繁,而数据变化不频繁的配置信息是非常合适添加一个中间缓存的比如Redis,那么就算配置表有1000条数据,那么将活跃数据缓存到Redis中那么流量就不会打到数据库了,那么对于这样的设计,会被频繁访问小表也是可以不用添加索引的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/329700.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAP PRD覆盖QAS 替代方案构想

随着时间的推移&#xff0c;SAP PRD的数据跟QAS的差异会越来越大&#xff0c;一般是定期PRD覆盖QAS。但是在没有BASIS的情况下&#xff0c;没有这块经验的情况下&#xff0c;也没有外部支持的情况下&#xff0c;贸然做这个事情也是有风险的&#xff0c;有没有替代方案&#xff…

算法2:滑动窗口(上)

文章目录 长度最小子数组无重复字符的最长子串[最大连续 1 的个数III](https://leetcode.cn/problems/max-consecutive-ones-iii/description/)将x减到0的最小操作数 长度最小子数组 class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {in…

vue3中基于element-plus封装一个表格弹框组件,要求可以单选和多选table数据

单选&#xff1a; <template><SelectMaterialref"selectMaterialRef"check"checkbox"select"selectMaterial"></SelectMaterial><el-button type"primary" size"small" icon"el-icon-plus"…

Web API——获取DOM元素

目录 1、根据选择器来获取DOM元素 2.、根据选择器来获取DOM元素伪数组 3、根据id获取一个元素 4、通过标签类型名获取所有该标签的元素 5、通过类名获取元素 目标&#xff1a;能查找/获取DOM对象 1、根据选择器来获取DOM元素 语法&#xff1a; document.querySelector(css选择…

RedisTemplate操作Redis, 看这一篇文章就够了

文章目录 1. String 命令1.1 添加缓存1.2 设置过期时间(单独设置)1.3 获取缓存值1.4 删除key1.5 顺序递增1.6 顺序递减1.7 常用的 2. Hash命令2.1 添加缓存2.2 设置过期时间(单独设置)2.3 添加一个Map集合2.4 提取所有的小key2.5 提取所有的value值2.6 根据key提取value值2.7 获…

C语言-牛客-实现四舍五入

欢迎来到Harper.Lee的学习小世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu欢迎来后台找我哦&#xff01; 本篇博客总结C语言刷题的相关笔记~~~~ #牛客–实现四舍五入 题目描述&#xff1a;随机输入浮点数&#xff0c;输出四舍五入后的整数…

vue中数据已经改变了,但是table里面内容没更新渲染!

解决方案&#xff1a; 给table或者el-table标签上添加一个动态key值&#xff0c;只要数据发生改变&#xff0c;key值变动一下即可 标签上&#xff1a; :key“timeStamp” 初始data&#xff1a;timeStamp:0, 更新数据&#xff1a;this.timeStamp 这样每次更新数据&#xff…

【B站 heima】小兔鲜Vue3 项目学习笔记Day03

文章目录 Home1.Home整体结构搭建和分类实现2. banner轮播图功能3. Home 面板组件封装4.新鲜好物和人气推荐实现5. 图片懒加载指令实现6. Home- product产品列表实现7. Home-GoodsItem 组件封装 一级路由1. 整体认识和路由配置2. 面包屑导航3. 一级分类 - 轮播图的实现4. 激活状…

2024年5月天润融通JAVA二面15-20K

二面 1、聊项目 2、举例说明你在上家公司职级晋升的原因 3、开发者和管理者的区别&#xff0c;你怎么做管理者 4、对sass的理解&#xff0c;包括流程&#xff0c;技术选型 5、springboot如何把bean加载到ioc容器中&#xff0c;ioc容器的理解 6、一万个任务同时执行&#…

内网安全之搭建ADCS证书服务

在域控上安装ADCS服务时&#xff0c;默认会自动配置完LDAPS&#xff0c;如果不是在域控上安装ADCS服务&#xff0c;需要手动配置LDAPS 安装证书服务ADCS 打开服务器管理器——>添加角色和功能 选择“基于角色或基于功能的安装”选项&#xff0c;然后点击下一步 选择“从…

网络协议——Modbus-RTU

目录 1、简介 2、消息格式 3、Modbus寄存器种类说明 4、功能码01H 5、功能码02H 6、功能码03H 7、功能码04H 8、功能码05H 9、功能码06H 10、功能码0FH 11、功能码10H 1、简介 Modbus-RTU&#xff08;Remote Terminal Unit&#xff09;是一种串行通信协议&#xff0…

云和恩墨海外首秀在吉隆坡召开的2024中国智能科技与文化展览会

作为中马建交50周年官方重点推荐的活动之一&#xff0c;2024中国智能科技与文化展览会&#xff08;第四届&#xff09;于5月20至21日在毗邻吉隆坡双子塔的吉隆坡国际会展中心举办。本次展览会获得马来西亚科学技术创新部、马来西亚通讯部、中国驻马来西亚大使馆和马来西亚中华总…

使用Unsloth微调Llama3-Chinese-8B-Instruct中文开源大模型

使用Unsloth微调Llama3-Chinese-8B-Instruct中文开源大模型 微调Llama3-Chinese-8B-InstructLlama-3-Chinese-8B-InstructUnsloth环境设置下载预训练模型加载model、tokenizer设置LoRA训练参数准备数据集数据处理训练超参数配置开始训练模型推理保存LoRA模型加载模型保存完整模…

OpsManage基于docker的部署与使用

前言 自动化运维管理工具OpsManagerhttp://mp.weixin.qq.com/s?__bizMzk0NTQ3OTk3MQ&mid2247487736&idx1&snefef3a930b88649033f61942a77f42d2&chksmc31598b4f46211a240ffc5360ae238b27d0f495fcbe8dc18abdbd79bc25c00726f74a7312dd0&scene21#wechat_redi…

[IMX6ULL驱动开发]-Linux对中断的处理(一)

目录 中断概念的引入 ARM架构中断的流程 异常向量表 Linux系统对中断的处理 ARM对程序和中断的处理 Linux进程中断处理 中断概念的引入 如何理解中断&#xff0c;我们可以进行如下抽象。把CPU看做一个母亲&#xff0c;当它正在执行任务的时候&#xff0c;可以看为是一个母…

【css】引入背景图时候,路径写入@会报错

看报错信息 我的写法 解决办法 在前面加个~

ThreadLocal原理及使用

一、引言 在Java多线程编程中&#xff0c;ThreadLocal是一个非常有用的工具&#xff0c;它提供了一种将对象与线程关联起来的机制&#xff0c;使得每个线程都可以拥有自己独立的对象副本&#xff0c;从而避免了线程安全问题。然而&#xff0c;使用不当会导致内存泄漏问题。 二…

【VTKExamples::Texture】第六期 TextureThreshold

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例TextureThreshold,并解析接口vtkTexture,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~Y…

python使用base加密解密

原理 base编码是一种加密解密措施&#xff0c;目前常用的有base16、base32和base64。其大致原理比较简单。 以base64为例&#xff0c;base64加密后共有64中字符。其加密过程是编码后将每3个字节作为一组&#xff0c;这样每组就有3*824位。将每6位作为一个单位进行编码&#xf…

MySQL主从复制+读写分离(ShardingJDBC)

MySQL主从复制读写分离 MySQL主从复制介绍二进制日志&#xff1a; MySQL的主从复制原理如下搭建主从复制准备工作主库配置从库配置 测试 读写分离案例ShardingJDBC介绍数据库环境初始工程导入读写分离配置测试1). 保存数据2). 修改数据3). 查询数据4). 删除数据 MySQL主从复制 …