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

news2024/11/24 6:06:05

目录

    • 前言
    • 一、分析前准备
      • 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
    @Test
    public 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.coloradmin.cn/o/1690061.html

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

相关文章

普乐蛙VR元宇宙展厅VR航天航空知识长廊

有没有幻想过有生之年可以亲自开战斗机&#xff1f;还是大名鼎鼎的“歼-20”哦&#xff01;上到四五十岁的中年人&#xff0c;下到十几岁的小年轻&#xff0c;无论男女老少&#xff0c;没人能逃得过炫酷到飞起的新一代战斗机&#xff01;快跟上小编的脚步&#xff0c;带你去开V…

2024云曦期中考(部分复现)

目录 一、Web Web_SINGIN 好玩的PHP 渗透的本质 简简单单的文件上传 简简单单的sql ​编辑 二、Crypto Crypto_Singin easy_rsa 三、Misc easy_singin Xjpg 四、Pwn pwn_Sing 五、Reverse babyre easy xor 一、Web Web_SINGIN F12代码中就有flag&#xff0…

构建稳健、高效与安全的企业级API网关

在现代企业信息化建设中&#xff0c;各种微服务架构系统以及不同类型的管理系统广泛兴起&#xff0c;平台中的数据安全逐渐成为企业重视的部分&#xff0c;在iPaaS系统中&#xff0c;一个名为“企业级API网关”的功能出现在大众眼中&#xff0c;随着企业信息化建设的不断深入&a…

ubuntu server 24.04 网络 SSH等基础配置

1 安装参考上一篇: VMware Workstation 虚拟机安装 ubuntu 24.04 server 详细教程 服务器安装图形化界面-CSDN博客 2 网络配置 #安装 sudo apt install net-tools#查看 ifconfig #修改网络配置 sudo vim /etc/netplan/50-cloud-init.yaml network:version: 2ethernets:en…

远程PLC、工控设备异地调试,贝锐蒲公英异地组网方案简单高效

北京宇东宁科技有限公司专门提供非标机电设备&#xff0c;能够用于金属制品的加工制造。设备主要采用西门子的PLC作为控制系统&#xff0c;同时能够连接上位机用于产量、温度、压力、电机运行数据的监控&#xff0c;以及工厂的大屏呈现需求。目前&#xff0c;客户主要是市场上的…

人工智能的阴暗面:犯罪分子如何利用 AI 进行欺诈

在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正迅速成为推动各行各业生产力和创新的关键力量&#xff0c;而一些不法分子也开始探索如何将这些先进的工具用于他们自己的非法目的。从网络钓鱼到深度伪造&#xff0c;再到人肉搜索、越狱服务和身份验证系统的…

MySQL-性能分析

1、数据库服务器的优化步骤 2、查看系统性能参数 可以使用show status语句查询一些MySQL数据库服务器的性能参数 执行频率语法格式&#xff1a;show [ global | session ] status like 参数 &#xff1b;常用性能参数如下所示 参数名说明connection连接MySQL服务器的次数upti…

如何使用Unity XR Interaction Toolkit

使用环境&#xff1a; Unity2021.3.21f XR Interaction Toolkit v3.0.0 各类函数可用的&#xff1a; 简单项目配置&#xff1a; 第一步&#xff0c;导包&#xff08;samples可以不用导这么多&#xff0c;两个就够了&#xff09;&#xff1a; 第二步&#xff0c;构建场景&a…

c++|priority_queue

priority_queue 前置知识&#xff1a;仿函数priority_queue的模拟实现 前置知识&#xff1a;仿函数 template<class T> struct Less {bool operator()(const T& x, const T& y) // {return x < y;} };priority_queue的模拟实现 通过对priority_queue的底层…

element ui表格动态合并方法

懒得上代码直接截图了 1. 这种方法适合所有合并项全部在一起的 2.还方法可以选择从哪一列开始合并&#xff0c;或者像目录一样从前往后合并

使用 Elastic AI assistant for Observability 来分析日志

在今天的文章中&#xff0c;我们来参考之前的文章 “Elastic AI Assistant for Observability 和 Microsoft Azure OpenAI 入门” 来使用 Elastic AI assistant 分析日志。在本文章中&#xff0c;我们不使用 Azure clould。这样我们之间来进入主题&#xff0c;以免失去注意力。…

Live800:提升客服服务质量,企业应从这几个方面下功夫

客户服务质量&#xff0c;是企业为客户提供优质服务的一个重要衡量指标。通常来说&#xff0c;一个企业的客服部门在其经营活动中发挥着重要作用&#xff0c;是客户与企业之间沟通的桥梁。良好的客服服务&#xff0c;不仅能够提高客户满意度&#xff0c;还能增强企业品牌的美誉…

pcd点云江湖之处处碰壁:点云文件pcd加载02

江湖好汉&#xff0c;休走&#xff0c;废了半天力气把threejs自带的代码搬迁到自己项目中了&#xff0c;高高兴兴给领导看。领导一句话&#xff0c;顿时无奈&#xff1a;领导曰&#xff1a;点云单色太丑&#xff0c;能不能按照分类展示&#xff1f; 一句话难道英雄好汉&#xf…

Redis主从、哨兵、cluster集群的部署和细节

目录 1. 主从模式 为什么需要主从&#xff1f; 搭建主从架构 2. Sentinel(哨兵)模式 为什么需要哨兵模式&#xff1f; 搭建哨兵集群 哨兵集群 Go语言编程redis哨兵模式 有了哨兵&#xff0c;客户端连接谁&#xff1f; test1&#xff1a;redis节点主从切换 test2&am…

linux内核memory model

一、背景   操作系统的一个重要功能就是管理计算机中的各种硬件资源&#xff0c;比如说CPU、内存、显存、串口等&#xff0c;其中内存是这些资源中很珍贵的部分&#xff0c;所以为了能把内存管理好做了很多工作。硬件内存架构是不停地发展变化的&#xff0c;内核中管理内存的…

Python 实现Word (DOC或DOCX)与TXT文本格式互转

目录 引言 安装Python库 使用Python将Word转换为TXT文本格式 使用Python将TXT文本格式转换为Word 引言 Word文档和TXT文本文件是日常工作和生活中两种常见的文件格式&#xff0c;各有其特点和优势。Word文档能够保留丰富的格式设置&#xff0c;如字体、段落、表格、图片等…

Flink 生态对 Confluent / Kafka Schema Registry 支持情况的研究报告

文章目录 1. Flink CDC 对 Confluent Schema Registry 的支持情况2. Confluent Avro Format 对 Confluent Schema Registry 的支持情况3. 关键性结论 这几年&#xff0c;在流式链路上引入一个 Schema Registry 变得越来越流行&#xff0c;也越来越有必要&#xff0c; Schema Re…

HX6203是一个完整的电池充电器控制器的两个(8.4V)电池锂离子电池芯片IC

一般描述 该HX6203是一个完整的电池充电器控制器的两个(8.4V)电池锂离子电池。HX6203为快速充电锂离子电池提供了一种小巧、简单、高效的解决方案。一个外部检测电阻以高精度设置充电电流。 内部电阻分压器和精密参考设置的最终浮动电压为8.4V时&#xff0c;输入…

宁盾与深信服发布联合方案,解决云桌面及微软AD完整替代

自 Citrix 退出中国市场后&#xff0c;不少中大型企业关心国产云桌面脱离微软 AD 域是否还能正常工作。在2024年3月初&#xff0c;宁盾身份目录与深信服桌面云完成兼容互认证&#xff0c;对于企业的疑问给出了官方回应。 5月10日&#xff0c;在深信服《Citrix离场背景下&#…