【MySQL】SQL优化(九)

news2024/11/27 22:25:16

🚗MySQL学习·第九站~
🚩本文已收录至专栏:MySQL通关路
❤️文末附全文思维导图,感谢各位点赞收藏支持~

一.插入数据

(1) 小规模数据

如果我们需要一次性往数据库表中插入多条记录:

-- 例如我们需要插入大量数据
insert  into  tb_test  values(1,'tom');
insert  into  tb_test  values(2,'cat');
insert  into  tb_test  values(3,'jerry');
....

我们可以从以下三个方面进行优化~

(1.1) 批量插入数据

由于每次insert都需要与数据库建立连接,进行网络传输导致一定的性能损失,我们可以选择一次性插入多条数据,代替一条一条插入。

-- 例如上述多条插入改为
Insert  into  tb_test  values(1,'Tom'),(2,'Cat'),(3,'Jerry');

不过一次性插入数据不建议超过500~1000条,大批量数据我们也可以拆分为多个insert批量插入。

(1.2) 手动控制事务

由于MySQL中事务提交的方式默认是自动提交的,也就是说当我们执行完一条insert语句后,他就会自动提交事务,如此可能会涉及到频繁的事务开启与提交。因此,我们还可以手动控制事务,减少事务开关所花费的时间

-- 多条插入手动控制事务
start  transaction;   -- 开启事务
insert  into  tb_test  values(1,'Tom'),(2,'Cat'),(3,'Jerry');
insert  into  tb_test  values(4,'Tom'),(5,'Cat'),(6,'Jerry');
insert  into  tb_test  values(7,'Tom'),(8,'Cat'),(9,'Jerry');
commit;    -- 提交事务

(1.3) 主键顺序插入

由于主键索引的存在,每次插入数据都可能会重新组织索引结构,因此,主键顺序插入,性能要高于乱序插入。

-- 主键乱序插入 : 8  1  9  21  88  2  4  15  89  5  7  3  
-- 主键顺序插入 : 1  2  3  4  5  7  8  9  15  21  88  89
insert  into  tb_test  values(1,'Tom'),(2,'Cat'),(3,'Jerry');  -- 顺序插入
insert  into  tb_test  values(5,'Cat'),(6,'Jerry'),(4,'Tom');  -- 乱序插入

(2) 大批量数据

如果一次性需要插入大批量数据(比如: 几百万的记录),使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令进行插入。通过load指令我们可以一次性将本地文件当中的数据全部加载进数据库表结构中。
在这里插入图片描述

可以执行如下指令,将数据脚本文件中的数据加载到表结构中:

  • (1)客户端连接服务端时,加上参数 -–local-infile
 mysql –-local-infile -u root -p 
 -- -–local-infile 表示需要加载本地文件
  • (2)设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
set  global  local_infile = 1;
  • (3)执行load指令将准备好的数据,加载到表结构中
load  data  local  infile  '/root/sql1.log'  into  table  tb_user  fields  
terminated  by  ','  lines  terminated  by  '\n' ; 

--  local  infile  '需要加载的文件路径'
--  into  table  需要插入到哪张表
--  fields terminated  by  '字段分隔符'
--  lines  terminated  by  '行分隔符'

在这里插入图片描述

二.主键优化

在满足业务需求的情况下,尽量遵循以下原则设计主键。

(1) 降低主键的长度

对于一张表来说主键索引只有一个,但是二级索引可能会有很多个,在二级索引的叶子节点当中挂的就是数据的主键,因此,如果主键长度比较长且二级索引比较多,将会占用大量的磁盘空间。
在这里插入图片描述

(2) 顺序插入

在条件允许的情况下,使用AUTO_INCREMENT自增主键,顺序插入数据。

在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,行数据都是存储在聚集索引的叶子节点上的。
在这里插入图片描述

而数据行是记录在逻辑结构 page 页中的,而每一个页的大小是固定的,默认16K。 那也就意味着, 一个页中所存储的行也是有限的,如果插入的数据行row在该页存储不下,将会存储到下一个页中,页与页之间会通过指针连接。
在这里插入图片描述

  • 主键顺序插入效果
  1. 从磁盘中申请页, 主键顺序插入

在这里插入图片描述

  1. 第一个页没有满,继续往第一页插入

在这里插入图片描述

  1. 当第一个也写满之后,再写入第二个页,页与页之间会通过指针连接

在这里插入图片描述

  1. 当第二页写满了,再往第三页写入

在这里插入图片描述

如此往复,没有任何额外损耗性能的情况。

  • 主键乱序插入效果
  1. 假如1#,2#页都已经写满了

在这里插入图片描述

  1. 此时再插入id为50的记录

在这里插入图片描述

  1. 按照顺序,应该存储在47之后

在这里插入图片描述

  1. 此时会开辟一个新的页 3#

在这里插入图片描述

  1. 但是并不会直接将50存入3#页,而是会将1#页后一半的数据,移动到3#页,然后在3#页,插入50。

在这里插入图片描述

  1. 移动数据,并插入id为50的数据之后,那么此时,这三个页之间的数据顺序是有问题的。 1#的下一个 页,应该是3#, 3#的下一个页是2#。 所以,此时,需要重新设置链表指针

在这里插入图片描述

上述的这种现象,称之为 “页分裂”,是比较耗费性能的操作

页分裂指的是:页可以为空,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果一行数据过大,会行 溢出),根据主键排列

(3) 避免对主键的修改

尽量不要使用有意义的值作为主键,如身份证号,避免在进行业务操作对主键产生修改操作。这是因为插入修改删除操作都会导致数据库重新组织索引结构。

三.order by优化

(1) 排序说明

MySQL的排序,有两种方式:

  • Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。
  • Using index : 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要 额外排序,操作效率高。

对于以上的两种排序方式,Using index的性能高,而Using filesort的性能低,我们在优化排序 操作时,尽量要优化为 Using index。

  • 排序字段值没有索引,Using filesort

在这里插入图片描述

  • 为排序字段值创建索引后,Using index

在这里插入图片描述

(2) 相关情况

  1. 由于我们在MySQL中创建的索引,默认的叶子节点是从小到大排序的。如果我们在查询的时候,order by是从大到小即降序desc,那么除了出现 Using index, 也会出现了 Backward index scan,这个代表反向扫描索引。 在 MySQL8版本中,支持降序索引,我们也可以创建降序索引。

在这里插入图片描述

-- 语法
create index 索引名 on 表名(字段名 desc);

在这里插入图片描述

  1. 排序时,也需要满足最左前缀法则(与where条件不同的是,此时必须按照创建索引时的顺序进行排序),否则也会出现 filesort。

在这里插入图片描述

因为在创建索引的时候, age是第一个 字段,phone是第二个字段,所以排序时,也就该按照这个顺序来,否则就会出现 Using filesort

  1. 在条件允许的情况下,尽量使用覆盖索引代替*,否则由于回表查询依旧会出现Using filesort

在这里插入图片描述

四.group by优化

与order by类似,分组就相当于大范围的排序。我们同样可以通过使用索引字段进行分组来提高效率。

在这里插入图片描述

此外,对于分组操作,在使用联合索引时,也是符合最左前缀法则的。例如下面:我们发现,如果仅仅根据age分组,就会出现 Using temporary ;而如果是 根据 profession,age两个字段同时分组,则不会出现 Using temporary。

在这里插入图片描述

五.limit优化

在数据量比较大时,如果进行limit分页查询,在查询时,越往后,分页查询效率越低。这是因为当在进行分页查询时,例如执行 limit 2000000,10 ,此时需要MySQL排序前2000010 记 录,仅仅返回 2000000 - 2000010 的记录,其他记录丢弃,查询排序的代价非常大。

在这里插入图片描述

通过测试我们会看到,分页越往后,查询效率越低。

  • 一般在进行分页查询时,我们可以通过 覆盖索引 + 子查询 的形式进行优化以提高性能。
--  select  *  from  tb_sku limit 9000000,10;
-- 例如对于上述测试示例 9000000,10 我们可以进行如下优化
explain select * from tb_sku t, (select id from tb_sku order by id limit 9000000,10) a where t.id  =  a.id;

在这里插入图片描述

测试我们可以看到,耗费时间缩短了了近7秒,但是同时也增加了SQL语句复杂度,需要我们根据自身业务情况选择使用~

六.count优化

如果在数据量很大的情况下执行count操作是非常耗时的。

  • MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个 数,效率很高; 但是如果是带条件的count,MyISAM也慢。
  • InnoDB 引擎在执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出 来,然后累积计数,比较耗时。

如果说要提升InnoDB表的count效率,主要的优化思路是:

  1. 自己计数,可以借助于redis这样的数据库进行,例如,插入一条数据,进行+1记录,删除一条数据进行-1记录。

  2. 通过改进count的用法来提升count的效率。count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是 NULL,累计值就加 1,否则不加,最后返回累计值,他有着如下四种不同的写法:

count用法含义
count(主键)InnoDB 引擎会遍历整张表,把每一行的 主键id 值都取出来,返回给服务层。 服务层拿到主键后,直接按行进行累加(主键不可能为null)
count(字段)没有not null 约束 : InnoDB 引擎会遍历整张表把每一行的字段值都取出 来,返回给服务层,服务层判断是否为null,不为null,计数累加。 有not null 约束:InnoDB 引擎会遍历整张表把每一行的字段值都取出来,返 回给服务层,直接按行进行累加。
count(数字)InnoDB 引擎遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1” 进去,直接按行进行累加。
count(*)InnoDB引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接 按行进行累加

按照效率排序:count(字段) < count(主键 id) < count(1) ≈ count(*),所以尽量使用 count(*)

七.update优化

InnoDB默认事务级别使用的是行锁,但是行锁是针对索引加的锁,不是针对记录加的锁 ,并且该索引不能失效,否则会从行锁 升级为表锁 。也就是说在开启事务时:

  • 我们能同时根据带有主键索引的不同id字段修改行记录
update  course  set  name = 'javaEE' where id  =  1 ;
update  course  set  name = 'Vue' where id  =  4 ;
  • 但是无法同时根据不带索引的name字段修改行记录,因为此时行锁会升级为表锁,无法操作。
update course set name = 'SpringBoot' where name = 'PHP' ;
update update course set name = 'SpringBoot' where name = 'JS' ;

也就是说为了避免行锁升级为表锁影响执行效率,我们应当根据索引字段来进行更新操作。

八.全文概览

在这里插入图片描述

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

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

相关文章

3.安装kubesphere

1.本地存储动态 PVC # 在所有节点安装 iSCSI 协议客户端&#xff08;OpenEBS 需要该协议提供存储支持&#xff09; yum install iscsi-initiator-utils -y # 设置开机启动 systemctl enable --now iscsid # 启动服务 systemctl start iscsid # 查看服务状态 systemctl status …

第三大的数

414、第三大的数 class Solution {public int thirdMax(int[] nums) {Arrays.sort(nums);int tempnums[0];int ansnums[0];int count 0;// if(nums.length<3){// return nums[nums.length-1];// }// else {for(int inums.length-1;i>0;i--){if (nums[i]>nums[i…

如何提高自己的软件测试水平之bug定位

同学们在面试投简历的时候会经常看到人家公司JD上写的要求之一&#xff0c;如下&#xff1a; 这句话大家不要以为随便写写的&#xff0c;在我工作的十几年过程中起码见过10个以上试用期没过的公司新人&#xff0c;公司在衡量一个测试工程师是否专业的标准之一就是&#xff1a;…

常用的数据结构 JAVA

目录 1、线性表2、栈&#xff1a;3、队列&#xff1a; 1、线性表 List<Object> narnat new ArrayList<>();ArrayList&#xff1a;动态数组 1、可以嵌套使用 2、add(x)添加元素x&#xff0c;remove(index)删除某个位置的元素 3、注意list是指向性的&#xff0c…

appium2.x 最新安装教程来了!不用再装 appium desktop 了!

前言 新的appium已经舍弃了appium-server&#xff0c;重新回归到只有命令行安装和启动appium服务。 本文是基于最新的appium2.x的安装教程。正想学习使用appium的不要错过。 1、安装最新版本的node.js 下载地址&#xff1a;https://nodejs.org/en&#xff0c;一路安装完成即…

SpringCloud学习笔记(五)ElasticSearch介绍

一、什么是ElasticSearch ElasticSearch是一款开源搜索引擎&#xff0c;可以帮助我们从海量数据中快速找到需要的内容ElasticSearch结合kibana、Logstash、Beats&#xff0c;也就是elastic stack&#xff08;ELK&#xff09;。被广泛应用在日志数据分析、实时监控等领域Elasti…

JAVA 正则表达式(heima)

JAVA 正则表达式&#xff08;heima&#xff09; public class RegexDemo01 {/** 正则表达式介绍&#xff1a;本质来说就是一个字符串&#xff0c;字符串中可以指定规则&#xff0c;来对其他字符串进行校验。* public boolean matches(String regex):根据传入的正则表达式&#…

Jmap-JVM(十六)

上篇文章说了ZGC是jdk11加入的&#xff0c;他是未来jvm垃圾收集器的奠定者&#xff0c;满足TB级别内存处理&#xff0c;STW时间保持在10ms以下。 Jmap 我们可以先通过jmap -histo 进程ip 来查看&#xff0c;但是这样看不太清晰&#xff0c;我们可以用这行命令生成一个文件&…

Vue中TodoList案例_动画

MyItem.vue : 主要是引入了import animate.css样式库&#xff0c;animate.css样式库配置见上一篇文章animate.css样式库&#xff0c;然后再li标签外套了transition标签&#xff0c;引用了name里面的名称是animate.css拿过来的&#xff0c;绑定了enter-active-class和leave-act…

前端实现导出excel表格

需求&#xff1a;实现勾选行导出为表格 一、安装插件 npm install --save file-saver xlsx运行项目报如下警告的话 运行npm install xlsx0.16.0 --save 来降低版本号&#xff08;最初我安装的版本号是0.18.16的版本&#xff09;再次运行项目就不会报如下警告了 二、新建一个ex…

嵌入式开发:单片机嵌入式Linux学习路径

SOC&#xff08;System on a Chip&#xff09;的本质区别在于架构和功能。低端SOC如基于Cortex-M架构的芯片&#xff0c;如STM32和NXP LPC1xxx系列&#xff0c;不具备MMU&#xff08;Memory Management Unit&#xff09;&#xff0c;适用于轻量级实时操作系统如uCOS和FreeRTOS。…

SOC FPGA之HPS模型设计(一)

目录 一、建立HPS硬件系统模型 1.1 GHRD 1.2 从0开始搭建HPS 1.2.1 FPGA Interfaces 1.2.1.1 General 1.2.1.2 AXI Bridge 1.2.1.3 FPGA-to-HPS SDRAM Interface 1.2.1.4 DMA Peripheral Request 1.2.1.5 Interrupts 1.2.1.6 EMAC ptp interface 1.2.2 Peripheral P…

PostMan+Jmeter工具介绍及安装

目录 一、PostMan介绍​编辑 二、下载安装 三、Postman与Jmeter的区别 一、开发语言区别&#xff1a; 二、使用范围区别&#xff1a; 三、使用区别&#xff1a; 四、Jmeter安装 附一个详细的Jmeter按照新手使用教程&#xff0c;感谢作者&#xff0c;亲测有效。 五、Jme…

Linux:Linux的发展史和作用有哪些?

文章目录 Linux是什么&#xff1f;Linux的开源特征为什么要学习Linux&#xff1f;Linux的应用场景有哪些&#xff1f; Linux是什么&#xff1f; 简单来说&#xff0c;Linux就是操作系统&#xff0c;它和Windows等软件一样&#xff0c;都只是操作系统&#xff0c;并无区别 Linu…

linux查看系统版本、内存、CPU等信息

一、查看linux内核版本信息&#xff08;两种方法&#xff09; 1. cat /proc/version linux查看当前操作系统内核版本信息 2. uname -a linux查看当前操作系统内核版本信息 二、查看linux系统版本信息&#xff08;3种方法&#xff09; 1. lsb_release -a 可列出所有版本…

链表踏歌:独具慧眼,雕琢重复元素藏身匿迹

本篇博客会讲解力扣“83. 删除排序链表中的重复元素”的解题思路&#xff0c;这是题目链接。 由于链表是排好序的&#xff0c;我们可以通过遍历一次链表的方式&#xff0c;删除所有重复的结点。具体来说&#xff0c; 如果链表为空&#xff0c;则不需要删除&#xff0c;直接返回…

你能说说“淘宝购物车”怎么测试么?

前言 今天我给大家整理一篇面试高频问到的问题“淘宝购物车”怎么测试。 测试思维 依然附上测试任何事物的测试思路&#xff1a; 第一步&#xff1a;梳理产品的核心业务流程&#xff1a;明白这是个什么项目&#xff0c;实现了什么业务&#xff0c;以及是怎么实现的&#xf…

自动化测试框架unittest与pytest的区别!

引言 前面文章已经介绍了python单元测试框架&#xff0c;大家平时经常使用的是unittest&#xff0c;因为它比较基础&#xff0c;并且可以进行二次开发&#xff0c;如果你的开发水平很高&#xff0c;集成开发自动化测试平台也是可以的。而这篇文章主要讲unittest与pytest的区别&…

感染了后缀为.maloxx勒索病毒如何应对?数据能够恢复吗?

引言&#xff1a; 网络安全威胁不断进化&#xff0c;勒索病毒作为其中一种恶意软件类型&#xff0c;给个人用户和企业带来了严重的数据安全问题。.maloxx勒索病毒&#xff08;maloxx Ransomware&#xff09;是最近出现的一种恶意软件&#xff0c;它能够加密受害者计算机中的数…

建筑设计项目管理系统推荐:哪个最适合您的业务?

建筑设计用什么项目管理系统好&#xff1f;Zoho Projects设计行业一体化解决方案适用于以建筑设计、景观规划、勘探设计、室内设计、灯光设计、幕墙设计、工业设计、品牌设计、平面设计为主要业务的设计公司、广告公司、建筑设计院等设计机构。围绕设计行业的核心业务需求&…