【MySQL】SQL优化(九)

这篇具有很好参考价值的文章主要介绍了【MySQL】SQL优化(九)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🚗MySQL学习·第九站~
🚩本文已收录至专栏: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指令我们可以一次性将本地文件当中的数据全部加载进数据库表结构中。
【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

  • (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  '行分隔符'

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

二.主键优化

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

(1) 降低主键的长度

对于一张表来说主键索引只有一个,但是二级索引可能会有很多个,在二级索引的叶子节点当中挂的就是数据的主键,因此,如果主键长度比较长且二级索引比较多,将会占用大量的磁盘空间。
【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

(2) 顺序插入

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

在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,行数据都是存储在聚集索引的叶子节点上的。
【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

而数据行是记录在逻辑结构 page 页中的,而每一个页的大小是固定的,默认16K。 那也就意味着, 一个页中所存储的行也是有限的,如果插入的数据行row在该页存储不下,将会存储到下一个页中,页与页之间会通过指针连接。
【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

页分裂指的是:页可以为空,也可以填充一半,也可以填充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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

(2) 相关情况

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

四.group by优化

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

五.limit优化

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

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

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

  • 一般在进行分页查询时,我们可以通过 覆盖索引 + 子查询 的形式进行优化以提高性能。
--  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;

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库

测试我们可以看到,耗费时间缩短了了近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' ;

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

八.全文概览

【MySQL】SQL优化(九),MySQL通关路,mysql,sql,数据库文章来源地址https://www.toymoban.com/news/detail-609531.html

到了这里,关于【MySQL】SQL优化(九)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL数据库基础(九):SQL约束

    文章目录 SQL约束 一、主键约束 二、非空约束 三、唯一约束 四、默认值约束 五、外键约束(了解) 六、总结 PRIMARY KEY 约束唯一标识数据库表中的每条记录。 主键必须包含唯一的值。 主键列不能包含 NULL 值。 每个表都应该有一个主键,并且每个表只能有一个主键。 遵循原

    2024年02月19日
    浏览(56)
  • 【数据库】MySQL 高级(进阶) SQL 语句

    location表格创建 store_info表格创建 显示表格中一个或数个字段的所有数据记录 不显示重复的数据记录 按照条件进行查询 在已知的字段数据取值范围内取值 另外还有not in命令,用法一致,表示显示不在指定范围内的字段的值。 在两个字段数据值之间取值,包含两边字段的数据

    2024年02月09日
    浏览(132)
  • 数据库应用:MySQL数据库SQL高级语句与操作

    目录 一、理论 1.克隆表与清空表 2.SQL高级语句 3.SQL函数 4.SQL高级操作 5.MySQL中6种常见的约束 二、实验  1.克隆表与清空表 2.SQL高级语句 3.SQL函数 4.SQL高级操作 5.主键表和外键表  三、总结 克隆表:将数据表的数据记录生成到新的表中。 (1)克隆表 ① 先创建再导入 ② 创建

    2024年02月13日
    浏览(75)
  • MySQL基础篇——MySQL数据库客户端连接,数据模型,SQL知识

    作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。   座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 目录 前言 一.客户端连接MySQL 二. 数据模型 1.关系型数据库(RDBMS) 2.数据模型 三.SQL 1.SQL通用语法 2.SQL分类 3.数据库操作 1). 查

    2024年02月06日
    浏览(71)
  • MySQL数据库基础(五):SQL语言讲解

    文章目录 SQL语言讲解 一、SQL概述 二、SQL语句分类 1、DDL 2、DML 3、DQL 4、DCL 三、SQL基本语法 1、SQL语句可以单行或多行书写,以分号结尾 2、可使用空格和缩进来增强语句的可读性 3、MySQL数据库的SQL语句不区分大小写,建议使用大写  4、可以使用单行与多行注释 四、总

    2024年02月19日
    浏览(54)
  • 【MySQL】数据库SQL语句之DML

    目录 前言: 一.DML添加数据 1.1给指定字段添加数据 1.2给全部字段添加数据 1.3批量添加数据 二.DML修改数据 三.DML删除数据 四.结尾   时隔一周,啊苏今天来更新啦,简单说说这周在做些什么吧,上课、看书、放松等,哈哈哈,所以博客就这样被搁了。   今天感觉不错,给大

    2024年02月08日
    浏览(62)
  • 【MySQL】——关系数据库标准语言SQL(大纲)

    🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:数据结构_IT闫的博客-CSDN博客 🐠数据结构:​​​​​​数据结构_IT闫的博客-CSDN博客 💎C++:C++_IT闫的博客-CSDN博

    2024年01月20日
    浏览(60)
  • 主流数据库(SQL Server、Mysql、Oracle)通过sql实现多行数据合为一行

    1、方法一:使用 STUFF 和 FOR XML PATH 进行多行合并成一行 (1)FOR XML PATH用法 FOR XML 是 SQL Server 提供的一种功能,允许您将查询结果转换为 XML 格式。 PATH 模式则是其中一种灵活的方式来构造自定义的XML结构。 1、基本字符串连接 : 当您想从单列中提取所有行的数据并连接成一

    2024年04月10日
    浏览(57)
  • MySQL数据库入门到精通1--基础篇(MySQL概述,SQL)

    目前主流的关系型数据库管理系统: Oracle:大型的收费数据库,Oracle公司产品,价格昂贵。 MySQL:开源免费的中小型数据库,后来Sun公司收购了MySQL,而Oracle又收购了Sun公司。 目前Oracle推出了收费版本的MySQL,也提供了免费的社区版本。 SQL Server:Microsoft 公司推出的收费的中

    2024年02月07日
    浏览(48)
  • 如何将 .sql 文件导入到 MySQL 数据库?

    导入 SQL 文件到 MySQL 数据库是一个常见的任务,本文将介绍如何执行该操作。我们将逐步讲解具体的步骤,帮助您完成这个过程。 首先,在您的计算机上打开命令提示符或终端窗口。这将是执行导入操作的地方。 在执行导入操作之前,请确保您的计算机已安装并且可以从命

    2024年02月11日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包