SQL优化相关

news2024/9/8 23:49:07

文章目录

  • SQL优化
    • 1. 数据插入
    • 2. 主键优化
      • 页分裂
      • 页合并
      • 索引设计原则
    • 3. order by 优化
    • 4. group by 优化
    • 5. limit优化
    • 6. count优化
    • 7. update 优化


SQL优化

1. 数据插入

当我们需要插入多条数据时候,建议使用批量插入,因为每次插入数据都会执行一条SQL,都要进行网络传输涉及到TCP建立连接这么一个过程,所以建议使用批量插入

不推荐写法

insert into user (id,name,age) value (1,'张三'18)insert into user (id,name,age) value (2,'李四'18)insert into user (id,name,age) value (3,'王五'18)

建议使用批量插入

insert into user (id,name,age) value (1,'张三'18),(2,'李四'18),(3,'王五'18)

手动控制事务,因为事务的开启和提交页需要一定的开销,那么我们就可以手动控制事务

start transaction;
insert into user (id,name,age) value (1,'张三'18),(2,'李四'18),(3,'王五'18)insert into user (id,name,age) value (4,'姜子牙'18),(5,'嬴政'18),(6,'孙悟空'18)commit;

受到MySQL索引结构的影响,对于主键的插入建议要顺序进行插入

插入大批量数据,插入大批量数据不建议使用insert语句,建议使用load,指定从本地文件中读取,指定一条数据列之间的分隔符以及每一条数据的分割付,如下

-- 客户端连接时,加上参数 --local-infile
mysql --local-infile -uroot -p
-- 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
set global local_infile = 1;
-- 使用load命令进行导入
load data local infile '/root/load_user_100w_sort.sql' into table test fields terminated by ',' lines terminated by '\n';

部分文件数据:

在这里插入图片描述

表结构

mysql> desc test;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id     | int(11)     | YES  |     | NULL    |       |
| name   | varchar(32) | YES  |     | NULL    |       |
| school | varchar(32) | YES  |     | NULL    |       |
| info   | varchar(32) | YES  |     | NULL    |       |
| time   | datetime    | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+

2. 主键优化

在InnoDB存储引擎中,表的数据都是根据主键顺序存放的,这种方式称为索引组织表。每一行的数据都是存在叶子节点

在这里插入图片描述

在InnoDB引擎中,每一个行数据都是存在逻辑结构page页中,每一页的大小是16K,也就是说一页可以存放多行数据,每一个页通过指针连接形成一个双向链表。

在这里插入图片描述

页分裂

当主键顺序插入时,会先把第一个页写满后,再写第二个页,以此类推,页与页之间使用指针进行连接。如图:

在这里插入图片描述

当主键乱序插入时,如图:

此时又要插入一个主键为11的数据,该怎么办?开辟一个新页,直接写到后面的新页中吗?显然不合理,因为这并不有序。

在这里插入图片描述

InnoDB真正的做法是,开辟一个新的页Page3,将Page1的后半部分数据移动到Page3中,并将数据插入到Page3中再修改页的指针指向。这就被称为页分裂

在这里插入图片描述

页合并

其实在一个页里删除一个数据的时候,数据并没有在物理磁盘上真正删除,而是做了一个标记,标记这个一块空间为可使用状态。

如下图每删除一个数据都会标记为可用状态,当删除后一个页的数据只被填充了50%的时候,InnoDB会寻找相邻的页看看是否能进行合并,从而优化空间。如下图,将12和11删除之后就将后面的页进行了合并

在这里插入图片描述

注意:**MERGE_THRESHOLD:合并页的阈值,可以自己设置,在创建表或者创建索引时指定。 **

索引设计原则

  • 在满足需求的情况下,尽量降低主键的长度,因为二级索引的叶子节点都是存放的主键,如果主键太索引比较多的时候就会占用磁盘空间,并且在搜索的时候增加磁盘I/O
  • 插入数据时,尽量使用顺序插入,选择使用AUTO_INCREMENT自增主键
  • 尽量不使用UUID或者身份证这一类没有顺序的数据,在插入数据的时候就会造成页分裂,并且UUID这种这么长的字符串作为索引也会增加磁盘I/O从而影响性能
  • 尽量不要对主键进行修改,如果对主键进行修改就需要动索引结构,这个代价是非常大的,因为很多二级索引的叶子节点就是主键,并且在聚集索引中主键也是按顺序排序的

3. order by 优化

在MySQL中有两中排序方式:

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

上诉两种排序方式,显然Using index的性能高,所以我们在对查询数据排序时候尽量优化到Using index

比如说查询user表中的id、age、phone,id为主键,通过age,phone进行升序排序

explain select id,age,phone from tb_user order by age,phone;

在这里插入图片描述

此时age和phone没有建立联合索引所以效率比较低,也就是Using filesort

-- 建立联合索引
create index age_phone_index on tb_user(age,phone);

在这里插入图片描述

建立联合索引后此时效率就提高了,变成了Using index,但如果按age升序排phone降序排序,最后这就不行了

explain select id,age,phone from tb_user order by age,phone desc;

在这里插入图片描述

此时就可以在建立索引时指定排序方式

create index age_phone_index_ad on tb_user(age asc,phone desc);

在这里插入图片描述

来看一下此时的索引结构:

在这里插入图片描述

order by优化原则

  • 根据排序字段建立索引,多字段排序的时候,也是遵循最左匹配原则的
  • 排序时尽量使用覆盖索引
  • 多字段排序,一个升序一个降序,此时在创建联合索引时指定排序规则ASC/DESC
  • 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k) ,因为如果大量数据排序超过排序缓冲区大小就在磁盘文件中进行排序,那么此时效率就会比较低

4. group by 优化

在对查询语句进行分组操作时,也可以建立索引提升效率。

比如说我要查每个专业有多少人,返回专业名称和人数

explain select profession,count(*) from tb_user group by profession;

执行结果

在这里插入图片描述

在没有建立索引的情况下,使用到了临时表,效率比较低,就可以建立索引。

create index pro_index on tb_user(profession);

在这里插入图片描述

所以,在分组操作中,我们需要通过以下两点进行优化,以提升性能:

  1. 在分组操作时,可以通过索引来提高效率。
  2. 分组操作时,索引的使用也是满足最左前缀法则的(针对联合索引)

5. limit优化

在数据量比较大的时候,如果进行limit分页查询,在查询的时候,越往后,分页查询效率越低。

因为在分页查询时,如果执行了limit 10 offset 2000000,此时需要MySQL排序前2000010 记录,仅仅返回 2000000 - 2000010 的记录,其他记录丢弃,查询排序的代价非常大

select * from user  limit 10 offset 2000000;

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

select * from user as a,(select id from user  limit 10 offset 2000000) as b where a.id=b.id;

6. count优化

当数据量比较大的时候,在执行count函数的时候也是比较耗时的

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

如果说要大幅度提升InnoDB表的count效率,主要的优化思路:自己计数(可以借助于redis这样的数据库进行,但是如果是带条件的count又比较麻烦了)。

count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是NULL,累计值就加 1,否则不加,最后返回累计值。

用法:

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

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

7. update 优化

如下图,两个事务对同一张表的不同行的数据进行修改,发生了阻塞,从而影响性能。

在这里插入图片描述

这一条sql 的where条件是一个普通字段,而InnoDB针对的是索引加锁,并不是对记录加锁,而且索引页不能失效,否则就会从行锁升级为表锁。

update tb_user set age=30 where name='姜子牙';

所以使用update的时候where条件建议使用索引字段,比如使用主键,避免锁升级从而影响并发下的性能

update tb_user set age=30 where id=24;

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

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

相关文章

使用YApi平台来管理接口

快速上手 进入YApi官网&#xff0c;进行注册登录https://yapi.pro/添加项目 3. 添加分类 4. 添加接口 5. 添加参数 添加返回数据 可以添加期望 验证 YAPI&#xff08;Yet Another Practice Interface&#xff09;是一个现代化的接口管理平台&#xff0c;由淘宝团队…

pip install albumentations安装下载遇19kB/s超级慢细水管解决办法

albumentations 是一个用于图像增强的 Python 库&#xff0c;它提供了丰富的图像变换功能&#xff0c;可以用于数据增强&#xff0c;从而提高深度学习模型的泛化能力。 直接安装命令&#xff1a; pip install albumentations但是如果半夜遇到这种19kB/s的下载速度 为头发着想&…

【通信模块】LoRa与LoRaWAN简介

LoRaWAN网络 技象科技相关文章总结&#xff0c;学习笔记&#xff0c;原文链接如下&#xff0c;转载请标明该出处&#xff1a; LORA&#xff1a; https://www.techphant.cn/tag/l-2 LORAWAN&#xff1a;https://www.techphant.cn/tag/l-3 其他&#xff1a;如LAN https://www…

网络通信---TCP协议1

今日内容 三次握手: 指建立tcp连接时&#xff0c;需要客户端和服务端总共发送三次报文确认连接。 四次挥手&#xff1a; 断开一个tcp连接&#xff0c;需要客户端和服务端发送四个报文以确认断开。 编程模型 TCP报文 客户端 服务端

第6篇文献研读生态廊道相关综述

该文发在生态与农村环境学报。该文章写了生态廊道概念的发展历程、生态廊道类型及功能、生态廊道划定的理论和方法、生态廊道的时间和国内大型生态廊道建设实践。 这篇文章可以让大家了解生态廊道的知识。

Rocketmq-5.3.0和对应dashboard的最新版本Docker镜像,本人亲自制作,部署十分方便,奉献给大家

一、Rocketmq 最新版本5.3.0&#xff0c;采用docker镜像安装方式 二、官方rocketmq镜像对内存等参数配置非常不灵活便利 为了快速、灵活部署rocketmq&#xff0c;以及能方便对其内存等参数进行设置&#xff0c;特意制作了关于它的docker镜像。 三、镜像获取 最新rocketmq-5.…

使用二进制来理解数据和二进制的计算

1 使用二进制来理解数据 和人类的思维习惯不同的是&#xff0c;计算机将把所有的东西数字化之后才会进行处理。那么计算机能理解的数字是什么样的呢&#xff1f;其实&#xff0c;在计算机内部&#xff0c;不管是什么信息都使用二进制来保存和处理的。 计算机为什么要用二进制…

芋道微服务全栈开发日记(商品sku数据归类为规格属性)

商品的每一条规格和属性在数据库里都是单一的一条数据&#xff0c;从数据库里查出来后&#xff0c;该怎么归类为对应的规格和属性值&#xff1f;如下图&#xff1a; 在商城模块&#xff0c;商品的单规格、多规格、单属性、多属性功能可以说是非常完整&#xff0c;如下图&#x…

搭建规范化的vue2项目

项目包含的库 Vue2VuexRouterEslintPrettier 环境 vue&#xff1a;2.6.14 eslint&#xff1a;7.32.0 prettier&#xff1a;2.4.1 eslint-plugin-prettier&#xff1a;4.0.0 eslint-plugin-vue&#xff1a;8.0.3 vue/cli&#xff1a;5.0.8 步骤 全局安装cli工具 npm in…

Vue3----扩展 element Plug card

扩展 element Plug card 增加全屏&#xff0c;折叠操作项 核心代码 <template><div class"cc-card-component"><el-card v-if"state.isShow" :class"state.class" :bodyStyle"bodyStyle" :shadow"props.shadow…

ic进阶|性能篇02:一文带你了解一种特殊的并行技术-展开!

本期文章让我们聊聊一种数字ic设计技术——展开&#xff0c;展开用于产生一个一次迭代就相当于原有结构的多次迭代的新电路结构。其相当于之前聊过的折叠技术的反向操作&#xff0c;折叠使用一个功能单元通过多次迭代来完成原有电路结构一次迭代的操作&#xff0c;相对于通过时…

访问控制列表(ACL)

文章目录 ACL原理与基本配置ACL分类ACL组成ACL规则的匹配与应用 ACL原理与基本配置 ACL(Access Control List&#xff0c;访问控制列表) 读取二层、三层、四层报文信息根据预先定义好的规则对报文进行过滤和分类实现网络访问控制、防止网络攻击和提高网络带宽利用率等目的提高…

USB3.0的等长要求到底是多少?

USB2.0与USB3.0接口的PCB布局布线要求PCB资源PCB联盟网 - Powered by Discuz! (pcbbar.com) 90欧姆阻抗&#xff0c;走差分线&#xff1a; 重点来了&#xff1a;

cf场+线性dp

Problem - B - Codeforces 思路&#xff1a; 这其实是一道数学题&#xff08;最开始一直在枚举&#xff0c;服啦&#xff09; 我们的目的是求最大利润 当a>b是时直接令k0,利润n*a即可 当a<b时存在两种情况&#xff1a; 1.b-a>n即所有b-i1的情况都>a&#xff0…

【数据结构】哈希表二叉搜索树详解

&#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ &#x1f48e;所属专栏&#xff1a;数据结构与算法学习 &#x1f341;1. 二叉搜索树 二叉搜索树也称为二叉查找树或二叉排序树&#xff0c;是一种特殊的二叉树结构&#xff0c;它的特点是&#xff1a; 1. 若左树不为空&am…

SCI算法!发文首选!参数优化下的BiLSTM-KAN模型回归预测,Python代码

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类算法的家人&#xff0c;可关注我的VX公众号&#xff1a;python算法小当家&#xff0c;不定期会有很多免费代码分享~ KAN是2024年最新的算法&#xff0c;是近期非常热门的一…

leetcode112. 路径总和 leetcode113. 路径总和II,图文并茂,教你完全弄懂DFS,附详细代码

leetcode112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 …

实验2-3-8 计算火车运行时间

//实验2-3-8 计算火车运行时间 /* 输入格式&#xff1a;输入在一行中给出2个4位正整数&#xff0c;其间以空格分隔&#xff0c;分别表示火车的出发时间和到达时间。 每个时间的格式为2位小时数&#xff08;00-23&#xff09;和2位分钟数&#xff08;00-59&#xff09;&#xff…

从0到1,AI我来了- (4)AI图片识别的理论知识-II

上篇文章&#xff0c;我们理解了我们程序的神经网络设计&#xff0c;这篇我们继续&#xff0c;把训练迭代过程分析一下&#xff0c;完成这两篇文章&#xff0c;下面问题&#xff0c;应该能回答了。 一张图片&#xff0c;如何被计算机读懂&#xff1f;pytorch 封装的网络&#…

C语言实现K均值聚类

K均值聚类(K_means)基础理论 K_means聚类是一种简单且广泛使用的聚类算法&#xff0c;它旨在将数据集中的样本划分为k个不同的聚类&#xff0c;其中k是事先指定的聚类数量&#xff0c;该算法的核心思想是迭代地优化聚类中心&#xff0c;以最小化每个样本与其所属聚类中心之间的…