MySQL 篇-深入了解视图、SQL 优化(主键优化、order by 优化、group by 优化、update 优化等)

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 SQL 优化

        1.1 SQL 优化 - 插入数据

        1.2 SQL 优化 - 主键优化

        1.2.1 页分裂

        1.2.2 页合并

        1.2.3 主键设计原则

        1.3 SQL 优化 - order by 优化

        1.3.1 单字段排序

        1.3.2 多字段排序

        1.4 SQL 优化 - group by 优化

        1.5 SQL 优化 - limit 优化

        1.6 SQL 优化 - count 优化

        1.7 SQL 优化 - update 优化

        2.0 视图概述

        2.1 检查选项 - cascaded、local

        2.2 视图 - 更新

        2.3 视图 - 作用


        1.0 SQL 优化

        SQL 优化包括多种技术和策略,旨在提高数据库插入、查询的性能。接着来介绍常用的 SQL 优化策略,比如主键优化、order by 优化、group by 优化等等,一般来说是通过索引的角度来思考如何提升查询性能。

        1.1 SQL 优化 - 插入数据

        当插入的数据量小于 1000 条时,可以使用 insert 优化:

        1)批量操作:

insert into table_name(column) values (),(),(),()...

        这种批量操作比一条一条插入数据的操作效率高很多,减少频繁的连接。

        2)手动提交事务:

/*开启事务*/
start transaction;
/*插入数据*/
insert into table_name(column) values (),()...;
insert into table_name(column) values (),()...;
insert into table_name(column) values (),()...;
insert into table_name(column) values (),()...;
insert into table_name(column) values (),()...;
/*提交数据*/
commit ;

        减少频繁的开启事务和提交事务、关闭事务,从而提高插入效率。

        3)主键顺序插入:

        主键按照顺序插入,简单来说:可以有效的防止页分裂,从而提高插入效率,因为一旦出现页分裂,就会即浪费空间,也会浪费时间。

减少页分裂的概率:

        当主键按照顺序插入时,新的数据通常会被添加到现有页的末尾。这种情况下,页面的填充程度不会迅速达到上限,从而减少了页分裂的发生。反之,如果随机插入数据,可能会导致某些页面迅速填满,进而触发页分裂。

提高插入效率:

        顺序插入减少了页面的随机 I/O 操作,因为数据是按顺序写入的,数据库可以更高效地管理数据页。页分裂不仅会消耗时间(因为需要创建新页并移动数据),还会导致额外的 I/O 操作,从而影响整体性能。

节省空间:

        页分裂会导致页中出现空隙和碎片,影响存储的效率。顺序插入有助于保持数据的紧凑性,最大限度地利用页面空间。

        当需要一次性插入大批量数据,使用 insert 语句插入性能就较低了,此时可以使用 MySQL 数据库提供的 load 指令进行插入,具体操作如下:

        1)客户端连接服务器端的时候,加上参数 '--local-infile':

mysql --local-infile -u root -p

        2)设置全局参数 local_infile 为 1,开启从本地加载文件导入数据的开关:

查看当前 local_infile 是否开启的语句:

select @@local_infile;

运行结果:

        默认是关闭状态。

开启 local_infile 的语句:

set global local_infile = 1;

 执行结果:

        3)执行 load 指令将准备好的数据,加载到表结构中:

load data local infile '需要添加的数据文件' into table '需要添加到具体的数据库' fields terminated by '字段之间的分割符' lines terminated by '行数据之间的分割符'; 

         这就可以将本地的大量数据一次性批量的导入到数据库中。

        1.2 SQL 优化 - 主键优化

        1.2.1 页分裂

        在 InnoDB 存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(IOT)。

        在索引中,非叶子节点存放的是索引,而叶子节点存储的是行数据,这些行数据默认是按照主键大小进行升序排序。不管是叶子节点还是非叶子节点,都是存储在页单位中,页的最大存储空间为 16 kb ,一旦超过了 16 kb,就需要创建新的空间进行存储,叶子节点之间,也就是页之间会有双向链表关联着。

        接着根据以上的条件,来了解数据的插入方式:

        1)按照主键顺序插入数据:

        按照主键顺序插入数据,一旦当前的页空间不足时,就会开辟新的空间,存储新插入的数据,且页之间会用链表进行关联。这样空间可以得到充足的利用,效率较高。

        2)暗战主键乱序插入数据:

        当插入主键序号为 50 的数据时,当需要在页之间插入发现空间已经不足了。

        先创建新的页空间,再从第一个页中获取页的后 50% 的数据放到新开辟的空间,接着将主键序号 50 的数据也放到新的空间中。

        最后,根据主键的大小利用双向链表进行重新关联起来。

        以上的过程就是页分裂,所以说,如果按照主键乱序插入数据,很可能会发生页分裂,从而导致空间的浪费,效率低下。

        1.2.2 页合并

        当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记为删除并且它的空间变得允许被其他记录声明使用。

        当页中删除的记录达到 MERGE_THRESHOLD(默认为页的 50%) ,InnoDB 会开始寻找最靠近的页(前或后)看看是否可以将两个页合并以优化空间使用。

页合并之前:

页合并之后:

        1.2.3 主键设计原则

        1)满足业务需要的情况下,尽量降低主键的长度。

        2)插入数据时,尽量选择顺序插入,选择使用 AUTO_INCREMENT 自增主键。

        3)尽量不要使用 UUID 做主键或者时其他自然主键,如身份证号。因为长度太长了,而且不是按照顺序插入。

        4)业务操作时,避免对主键的修改。

        1.3 SQL 优化 - order by 优化

        对于 order by 的优化,简单来说,就是在排序的时候,尽量通过索引来排序而且不进行回表查询的方式来获取到数据。

        1)Using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区 sort buffer 中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序,操作效率较低。

        2)Using index:通过有序索引顺序扫面直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。

        1.3.1 单字段排序

举个例子:

explain select book_id,book_price from book order by book_price;

加索引之前的结果:

        没有加索引的效率比较低,通过全表扫描,将符合条件的数据放到排序缓冲区再来完成排序操作。

        接着给 book_price 字段加上索引:

/*给字段添加索引*/
create index idx_book_price on book(book_price);
/*查看索引*/
show index from book;

执行结果:

        再对其进行排序:

explain select book_id,book_price from book order by book_price;

执行结果:

        可以看到查询计划用到了 using index,效率较高,用到了索引来获取排序结果,而且没有进行回表查询。

        如果使用 ' select * ' 语句:

explain select * from book order by book_price;

执行结果:

        即使 book_price 字段已经有索引,但是需要返回的结果为 ' * ' ,所以 MySQL 对其进行优化了,直接按照全表查询,再将符合条件的数据放到排序缓冲区中完成排序操作,最后再返回排序后的结果。即使该查询计划用到了 book_price 字段的索引,仍需要进行回表查询,不能直接获取到已经排序好的结果,所以是 using filesort 方式,效率比较低。

        因此避免使用 ' * ' 来查询,可以创建联合索引,选择需要的字段。 

        1.3.2 多字段排序

        对于排序规则有两个字段以上的情况,如果是都是按照升序排序,在构建联合索引的时候,默认就是按照升序排序的;如果需求是获取降序的结果,那么即使在构建索引过程中没有指定降序排序,在查询过程中仍然会走索引,仍然是用到了 using index 的方式。

        但是,对于多个字段的排序的方式不同,就需要在创建索引的时候,分别指定的排序方式,否则在查询的时候,没有对应的索引排序方式,就会走全表查询,使用 using filesore 的方式,效率较低。

        简单来说,进行排序查询的时候,需要注意查看是否有相对应的索引排序方式,如果有,那么就会使用 using index 方式;如果没有相对应的索引排序方式,那么就会使用 using filesore 方式,效率比较低。

        1.4 SQL 优化 - group by 优化

        同理,在进行分组查询的时候,尽量使用索引来查询,并且使用覆盖查询,创建联合索引。

举个例子:

        在添加索引之前进行分组查询:

explain select book_category, count(*) from book group by book_category;

执行结果:

        没有用到索引,效率不高。

        对 book_name、book_author、book_category 字段添加联合索引:

/*添加索引*/
create index idx_book_name_author_category on book(book_name,book_author,book_category);
/*查看索引*/
show index from book;

执行结果:

         接着查询分组:

explain select book_category, count(*) from book group by book_category;

执行结果:

        即使用到了索引进行分组查询,由于没有满足最左前缀法则,效率还是较低。

explain select book_name ,count(*) from book group by book_name;

 执行结果:

        1.5 SQL 优化 - limit 优化

        一般分页查询时,通过创建覆盖索引能够比较好的提高性能,可以通过覆盖索引加子查询形式进行优化。

        思路:先查询得到对应的 id,获取到的 id 当作一个表,再进行多表查询,条件就是 id 是否符合表中的 id 即可。这样在查询获取 id 的时候,可以根据主键索引来获取 id,在多表查询的时候,也是根据索引来进行查询的。

        如果查询直接是 ' * ' 的时候,会进行全表查询:

explain select * from book limit 1,2;

执行结果:

        而对于只查询返回 id 的时候,会走索引查询:

explain select book_id from book limit 1,2;

 执行结果:

        接着根据 id 来进行多表查询,查询返回 ' * ':

explain select * from book b1,(select book_id from book limit 2) b2 where b1.book_id = b2.book_id;

 执行结果:

        1.6 SQL 优化 - count 优化

        1)count(主键)

        InnoDB 引擎会遍历整张表,把每一行的主键 id 值都取出来,返回给服务层。服务层拿到主键后,直接按行进行累加(主键不可能为 null)。

        2)count(字段)

        没有 not null 约束:InnoDB 引擎会遍历整张表把每一行字段值都取出来,返回给服务层,服务层判断是否为 null,不为 null,计数累加。

        有 not null 约束:InnoDB 引擎会遍历整张表把每一行的字段都取出来,返回给服务层,直接按行进行累加。不需要进行判断是否为 null 。

        3)count(1)

        InnoDB 引擎遍历整张表,但不取值。服务层对于返回每一行,放一个数字 '1' 进去,直接按行进行累加。

        4)count(*)

        InnoDB 引擎并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。

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

        1.7 SQL 优化 - update 优化

        在对数据进行修改的时候,条件中的字段是存在索引且没有失效的时候,则会对索引进行加锁,也就是说其他线程再来对该行数据进行修改的时候会阻塞等待,直到锁被释放。如果条件中的字段不存在索引或者索引失效了,那么在对该表中的其他行数据进行修改的时候,会阻塞,因为从行锁升级为表锁了。

        简答来说,如果需要对数据进行修改的时候,最好给该字段加上索引,当给该字段加上索引之后,此时锁的是行数据,只对某一行正在操作的行数据进行加锁。操作不同的行数据不会影响,可以并发执行,只是针对已经执行操作的行数据再次去修改当前行数据的时候会出现阻塞。如果该字段没有索引或者索引失效了,那么就会进行锁升级,升级为表锁,会对整个表加锁,只要对表中的某一行数据进行操作,其他行数据也会阻塞,并发量大大降低,效率也随着降低。

举个例子:

        book_price 字段还没创建索引的时候:

        对 book_price 为 80 的行数据进行修改:

        由于没有创建索引,此时还是表锁,当修改数据还没提交之前,表锁还没释放,因此,其他并发操作的数据修改会受到影响,所以还在运行等待中。

        直到修改数据操作提交:

        这才成功获取到锁,再对数据进行修改。

        接着给 book_price 字段加上索引:

create index idx_book_price on book(book_price);show index from book;

执行结果:

        继续之前的操作:

        对 book_price 为 80 的行数据进行修改:

        可以发现,此时修改其他行数据还没等到当前行数据修改提交的时候,操作修改其他行数据没有出现阻塞情况。是因为此时锁的是行数据,操作相同行数据的时候,会阻塞等待,而操作不同行数据的时候,不会出现阻塞等待。这就是索引带来的好处,当该字段有索引的时候,锁的就是行数据,没有索引的时候,锁的就是表。

        这就大大增加了并发量,提高了效率。

        2.0 视图概述

        视图是一种虚拟存在的表。视图中的数据并不是在数据库中实际存在,行和列数据自定义视图的查询中使用的表,并且是在使用视图时动态生成的。

        简单来说,视图只保存了查询的 SQL 逻辑,不保存查询结果。所以在创建视图的时候,只要的工作就落在创建这条 SQL 查询语句上。

视图相关的 SQL 语句:

        1)创建语句:

create [or replace] view view_name as select 语句 [with [cascaded | local] check option];

举个例子:

/*根据 book 基表创建视图*/
create or replace view view_book as select book_name name,book_author author from book;

 执行结果:

        2)查询语句:

查看创建视图语句:
show create view view_name;查看视图数据:
select * from view_name;

举个例子:

-- 查看创建视图的语句
show create view view_book;

执行结果:

-- 查看视图中的数据
select * from view_book;

执行结果:

 

        3)修改语句:

方式一:

create [or replace] view view_name as select 语句 [with [cascaded | local] check option];

        可以发现方式一的修改语句与创建视图的 SQL 语句是一样的。 

方式二:

alter view view_name as select 语句 [with [cascaded | local] check option];

 举个例子:

-- 修改视图
alter view view_book as select book_id id,book_name name,book_author author from book;

执行结果:

 

        4)删除语句:

drop view if exists view_name;

举个例子:

-- 删除视图
drop view if exists view_book;

 

        2.1 检查选项 - cascaded、local

        对于视图中的数据的增删改查的操作,和表的操作语句几乎是一样的。只不过,在视图中进行增删改查的操作之前,可以对条件进行检查,满足条件就可以在表中操作数据,需要注意的是,实际是对表中的数据进行操作,视图只是映射基表中的数据。

        当使用 with check option 子句创建视图时, MySQL 会通过视图检查正在更改的每个行。例如插入、更新、删除。以使其符合视图的定义。MySQL 允许基于另一个视图创建视图,它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围,MySQL 提供了两个选项:cascaded、local,默认值为 cascaded 。

cascaded:

        当基于另一个视图创建的视图时,当前创建视图的时候有 with cascaded check option 语句,在视图对数据操作时,先会检查当前视图的条件,再去检查另一个视图的条件,也就是说,相当于另一个视图也会创建了 with cascaded check option 。

local:

        在基于另一个视图创建视图时,当前视图用到了 with local check option 语句,只会检查当前视图的条件,不会检查先前视图的条件。

        2.2 视图 - 更新

        要使视图可更新,视图中的行于基础表中的行之间必须存在一对一的关系。如果视图包含以下任何一项。则该视图不可更新:

        1)聚合函数或窗口函数(sun()、min()、max()、count() 等)

        2)DISTINCT

        3)GROUP BY

        4)HAVING

        5)UNION 或者 UNION ALL

        2.3 视图 - 作用

        1)简单:

        视图不仅可以简化用户对数据的理解,也可以简化他们的操作。哪些被经常使用的查询使用可以被定义为视图,从而使得用户不必为以后的操作每次指定全部的条件。

        2)安全:

        数据库可以授权,但不能授权到数据库特定行和特定的列上。通过视图用户只能查询和修改他们所见到的数据。

        3)数据独立

        视图可帮助用户屏蔽真实表结构变化带来的影响。

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

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

相关文章

重学SpringBoot3-集成Redis(五)之布隆过滤器

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;五&#xff09;之布隆过滤器 1. 什么是布隆过滤器&#xff1f;基本概念适用场景 2. 使用 Redis 实现布隆过滤器项目依赖Redis 配置…

【python实操】python小程序之对象的属性操作

引言 python小程序之对象的属性操作 文章目录 引言一、对象的属性操作1.1 题目1.2 代码1.3 代码解释 二、思考2.1 添加属性2.2 获取属性 一、对象的属性操作 1.1 题目 给对象添加属性 1.2 代码 class Cat:# 在缩进中书写⽅法def eat(self):# self 会⾃动出现,暂不管print(f…

【前端开发入门】前端开发环境配置

目录 引言一、Vscode编辑器安装1. 软件下载2. 软件安装3. 插件安装 二、Nodejs环境安装及版本控制1. 安装内容2. 使用nvm安装2.1 软件下载并安装2.2 nvm基本指令2.3 nvm下载过慢导致超时解决 三、git安装及配置1. 软件下载2. 软件安装3. 基础配置 四、总结 引言 本系列教程旨在…

知识图谱入门——5:Neo4j Desktop安装和使用手册(小白向:Cypher 查询语言:逐步教程!Neo4j 优缺点分析)

Neo4j简介 Neo4j 是一个基于图结构的 NoSQL 数据库&#xff0c;专门用于存储、查询和管理图形数据。它的核心思想是使用节点、关系和属性来描述数据。图数据库非常适合那些需要处理复杂关系的数据集&#xff0c;如社交网络、推荐系统、知识图谱等领域。 与传统的关系型数据库…

【韩顺平Java笔记】第7章:面向对象编程(基础部分)【227-261】

文章目录 227. 重载介绍228. 重载快速入门229. 重载使用细节230. 重载课堂练习1231. 232. 重载课堂练习2,3233. 可变参数使用233.1 基本概念233.2 基本语法233.3 快速入门案例 234. 可变参数细节235. 可变参数练习236. 作用域基本使用237. 作用域使用细节1238. 作用域使用细节2…

基于FPGA的ov5640摄像头图像采集(二)

之前讲过ov5640摄像头图像采集&#xff0c;但是只包了的摄像头驱动与数据对齐两部分&#xff0c;但是由于摄像头输入的像素时钟与HDMI输出的驱动时钟并不相同&#xff0c;所有需要利用DDR3来将像素数据进行缓存再将像素数据从DDR3中读出&#xff0c;对DDR3的读写参考米联客的IP…

Hallo部署指南

一、介绍 Hallo是由复旦大学、百度公司、苏黎世联邦理工学院和南京大学的研究人员共同提出的一个AI对口型肖像图像动画技术&#xff0c;可基于语音音频输入来驱动生成逼真且动态的肖像图像视频。 该框架采用了基于扩散的生成模型和分层音频驱动视觉合成模块&#xff0c;提高了…

独立站如何批量查收录,独立站批量查询收录的操作方法

独立站批量查询收录是SEO优化过程中的一项重要任务&#xff0c;它有助于网站管理员全面了解网站在搜索引擎中的表现情况。以下是一些常用的独立站批量查询收录的操作方法&#xff1a; 一、使用搜索引擎的Site指令结合自动化工具 编写脚本或配置爬虫&#xff1a; 利用Python、…

【Flutter】- 核心语法

文章目录 知识回顾前言源码分析1. 有状态组件2. 无状态组件3. 组件生命周期4. 常用组件Container组件Text组件Image组件布局组件row colum stack expandedElevntButton按钮拓展知识总结知识回顾 【Flutter】- 基础语法 前言 Flutter是以组件化的思想构建客户端页面的,类似于…

windows C++-创建数据流代理(二)

完整的数据流演示 下图显示了 dataflow_agent 类的完整数据流网络&#xff1a; 由于 run 方法是在一个单独的线程上调用的&#xff0c;因此在完全连接网络之前&#xff0c;其他线程可以将消息发送到网络。 _source 数据成员是一个 unbounded_buffer 对象&#xff0c;用于缓冲…

网站建设中常见的网站后台开发语言有哪几种,各自优缺点都是什么?

市场上常见的网站后台开发语言有PHP、Python、JavaScript、Ruby、Java和.NET等。这些语言各有其独特的优缺点&#xff0c;适用于不同的开发场景和需求。以下是对这些语言的具体介绍&#xff1a; PHP 优点&#xff1a;PHP是一种广泛用于Web开发的动态脚本语言&#xff0c;特别适…

Diffusion models(扩散模型) 是怎么工作的

前言 给一个提示词, Midjourney, Stable Diffusion 和 DALL-E 可以生成很好看的图片&#xff0c;那么它们是怎么工作的呢&#xff1f;它们都用了 Diffusion models&#xff08;扩散模型&#xff09; 这项技术。 Diffusion models 正在成为生命科学等领域的一项尖端技术&…

基于STM32的智能花盆浇水系统设计

引言 本项目设计了一个基于STM32的智能花盆浇水系统。该系统通过土壤湿度传感器检测土壤湿度&#xff0c;当湿度低于设定阈值时&#xff0c;自动启动水泵进行浇水。它还结合了温湿度传感器用于环境监测。该项目展示了STM32在传感器集成、自动控制和节水智能化应用中的作用。 …

Nginx05-基础配置案例

零、文章目录 Nginx05-基础配置案例 1、案例需求 &#xff08;1&#xff09;有如下访问 http://192.168.119.161:8081/server1/location1 访问的是&#xff1a;index_sr1_location1.htmlhttp://192.168.119.161:8081/server1/location2 访问的是&#xff1a;index_sr1_loca…

YoloV9改进策略:BackBone改进|CAFormer在YoloV9中的创新应用,显著提升目标检测性能

摘要 在目标检测领域,模型性能的提升一直是研究者和开发者们关注的重点。近期,我们尝试将CAFormer模块引入YoloV9模型中,以替换其原有的主干网络,这一创新性的改进带来了显著的性能提升。 CAFormer,作为MetaFormer框架下的一个变体,结合了深度可分离卷积和普通自注意力…

Ansible学习之ansible-pull命令

想要知道ansible-pull是用来做什么的&#xff0c;就需要了解Ansible的工作模&#xff0c;Ansible的工作模式有两种&#xff1a; push模式 push推送&#xff0c;这是Ansible的默认模式&#xff0c;在主控机上编排好playbook文件&#xff0c;push到远程主机上来执行。pull模式 p…

远程调用的问题以及eureka原理

目录 服务调用出现的问题 问题分析 解决方案&#xff08;eureka原理&#xff09; eureka&#xff08;两个角色&#xff09; eureka的解决方案 此过程出现的问题 eureka的作用 总结 服务调用出现的问题 服务消费者该如何获取服务提供者的地址信息&#xff1f;如果有多个…

系统架构设计师论文《论企业应用系统的数据持久层架构设计》精选试读

论文真题 数据持久层&#xff08;Data Persistence Layer&#xff09;通常位于企业应用系统的业务逻辑层和数据源层之间&#xff0c;为整个项目提供一个高层、统一、安全、并发的数据持久机制&#xff0c;完成对各种数据进行持久化的编程工作&#xff0c;并为系统业务逻辑层提…

【SpringBoot】基础+JSR303数据校验

目录 一、Spring Boot概要 1. SpringBoot介绍 2. SpringBoot优点 3. SpringBoot缺点 4. 时代背景-微服务 二、Spring Boot 核心配置 1. Spring Boot配置文件分类 1.1 application.properties 1.2 application.yml 1.3 小结 2. YAML概述 3. YAML基础语法 3.1 注意事…

【教程】57帧! Mac电脑流畅运行黑神话悟空

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 1、先安装CrossOver。网上有许多和谐版&#xff0c;可自行搜索。&#xff08;pd虚拟机里运行黑神话估计够呛的&#xff09; 2、运行CrossOver&#xf…