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

目录

    • 前言
    • 一、分析前准备
      • 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.mzph.cn/pingmian/14780.shtml

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

相关文章

【小沐学GIS】GDAL库安装和使用(C++、Python)

文章目录 1、简介2、下载和编译&#xff08;C&#xff09;2.1 二进制构建2.1.1 Conda2.1.2 Vcpkg 2.2 源代码构建2.2.1 nmake.opt方式构建2.2.2 generate_vcxproj.bat方式构建 2.3 命令行测试2.3.1 获取S57海图数据 2.4 代码测试2.4.1 读取tiff信息 3、Python3.1 安装3.2 测试3…

零基础入门篇④ 初识Python(注释、编码规范、关键字...)

Python从入门到精通系列专栏面向零基础以及需要进阶的读者倾心打造,9.9元订阅即可享受付费专栏权益,一个专栏带你吃透Python,专栏分为零基础入门篇、模块篇、网络爬虫篇、Web开发篇、办公自动化篇、数据分析篇…学习不断,持续更新,火热订阅中🔥专栏订阅地址 👉Python从…

C语言 | Leetcode C语言题解之第110题平衡二叉树

题目&#xff1a; 题解&#xff1a; int height(struct TreeNode* root) {if (root NULL) {return 0;}int leftHeight height(root->left);int rightHeight height(root->right);if (leftHeight -1 || rightHeight -1 || fabs(leftHeight - rightHeight) > 1) {…

Android硬件渲染环境初始化

Android硬件渲染环境初始化 一.硬件加速渲染的开启1.ThreadedRenderer的初始化2.RenderProxy的创建 二.RenderProxy中组件的初始化1.RenderThread的创建2.CanvasContext的创建3.DrawFrameTask的初始化 三.RenderThread的启动1.RenderThread中组件的初始化2.RenderThread中任务的…

arXiv AI 综述列表(2024.05.20~2024.05.24)

公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 每周末更新&#xff0c;完整版进群获取。 Q 群在群文件&#xff0c;VX 群每周末更新。 目录 1. Beyond Traditional Single Object Tracking: A …

基于yolov2深度学习网络的昆虫检测算法matlab仿真,并输出昆虫数量和大小判决

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022A 3.部分核心程序 .......................................................... for i 1:12 % 遍历结…

播兔短剧模板:图鸟UI在前端短剧平台中的应用与实践

一、引言 随着移动互联网的快速发展&#xff0c;短剧平台因其短小精悍、内容丰富的特点&#xff0c;逐渐成为用户休闲娱乐的新宠。为了满足短剧平台对前端技术的需求&#xff0c;图鸟播兔短剧模板应运而生。该模板基于图鸟UI进行开发&#xff0c;采用纯前端技术&#xff0c;支…

【C语言回顾】文件操作

前言1. 文件打开模式2. 示例代码2.1 打开和关闭文件2.2 读写文件2.3 二进制文件操作 结语 #include<GUIQU.h> int main { 上期回顾: 【C语言回顾】动态内存管理 个人主页&#xff1a;C_GUIQU 专栏&#xff1a;【C语言学习】 return 一键三连; } 前言 各位小伙伴大家好&…

分享:怎么才能保证大数据查询的准确性?

随着大数据应用到金融风控领域&#xff0c;大数据越来越重要了&#xff0c;很多朋友在查大数据的时候都会遇到一个问题&#xff0c;那就是自己查询的大数据什么信息都没有&#xff0c;要么就是很少&#xff0c;这是什么原因呢?要怎么才能保证大数据查询的准确性呢?下面小编就…

Java进阶学习笔记3——static修饰成员方法

成员方法的分类&#xff1a; 类方法&#xff1a;有static修饰的成员方法&#xff0c;属于类&#xff1a; 成员方法&#xff1a;无static修饰的成员方法&#xff0c;属于对象。 Student类&#xff1a; package cn.ensource.d2_staticmethod;public class Student {double scor…

双拼打字,可以尝试这个练习平台

本文将介绍由本人开发的双拼练习平台打字侠&#xff0c;以及一些对新手学习双拼的建议。课程一共233课&#xff0c;共分为两大部分&#xff1a; 韵母键位&#xff0c;主要练习双拼中韵母对应的键盘键位&#xff0c;同时提供可视化的键盘指法示意图。 实战练习&#xff0c;同时…

Selenium常用命令(python版)

日升时奋斗&#xff0c;日落时自省 目录 1、Selenium 2、常见问题 1、Selenium 安装Python和配置环境没有涉及 注&#xff1a;如有侵权&#xff0c;立即删除 首先安装selenium包&#xff0c;安装方式很简单 pip install selenium 注:我这里已经安装好了&#xff0c;所以…

怎么一键消除路人?教你三个消除方法

怎么一键消除路人&#xff1f;在数字时代&#xff0c;摄影已成为我们记录生活、表达情感的重要方式。然而&#xff0c;完美的照片背后往往隐藏着一些不那么完美的元素——比如那些不经意间闯入镜头的路人。他们或许只是匆匆过客&#xff0c;但却足以破坏你精心构图的美好瞬间。…

分割文本文件

分割一个.txt文件&#xff0c;可以选择在命令行中使用split指令&#xff0c;或者编写一段脚本进行操作。以下是一个简单的Python脚本来分割文本文件&#xff1a; def split_file(file, lines):# Open source filewith open(file, r) as source:count 0atEOF Falsewhile not …

shell笔记脚本3

执行脚本文件demo2.sh, 观察打印VAR4效果 执行脚本文件后, 在交互式Shell环境打印VAR4, 观察打印VAR4效果 结论 全局变量在当前Shell环境与子Shell环境中可用, 父Shell环境中不可用 小结 自定义变量的分类 自定义局部变量: 就是在一个脚本文件内部使用 var_namevalue 自…

128天的创意之旅:从初心到成就,我的博客创作纪念日回顾

文章目录 &#x1f680;机缘&#xff1a;初心的种子——回望创作之旅的启航&#x1f308;收获&#xff1a;成长的果实——128天创作之旅的宝贵馈赠❤️日常&#xff1a;创作与生活的交织&#x1f44a;成就&#xff1a;代码的艺术&#x1f6b2;憧憬&#xff1a;未来的蓝图 &…

Mujoco仿真【xml文件的学习 3】

在学习Mujoco仿真的过程中&#xff0c;为了与时俱进&#xff0c;之前的mujoco210版本不再使用&#xff0c;改用了mujoco-3.1.4版本&#xff0c;下面继续mujoco仿真的学习&#xff01; 先前关于mujoco的学习博客汇总如下&#xff1a; 强化学习&#xff1a;MuJoCo机器人强化学习…

2024最新(PC+WEB+IOS+Android)即时通讯系统客户端仿默往IM源码下载

2024最新(PCWEBIOSAndroid)即时通讯系统客户端仿默往IM源码下载(总大小约2.4G&#xff09; 系统功能配置灵活、海量并发、稳定可靠、数据安全&#xff0c;2小时快速部署、数据安全、单聊群聊、系统通知等通信功能&#xff0c;支持App、PC、Web等多端快速接入。 群功能&#xf…

Linux 软件包管理器 yum的下载、功能介绍及使用

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 Linux下的三种软件安装方…

panic对defer语句的执行的影响

1.主线程中的panic会直接导致所有正在运行的go协程无法执行,还会导致声明在它之后的defer语句无法执行。 package mainimport ("fmt""time" )func main() {defer fmt.Println("defer1") //声明在panic之前的defer会执行go func() {defer fmt.Pri…