SQL优化相关

文章目录

  • 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.mzph.cn/web/50011.shtml

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

相关文章

【Linux】多线程4——线程同步/条件变量

1.Linux线程同步 1.1.同步概念与线程饥饿问题 先来理解同步的概念 什么是线程同步 在一般情况下&#xff0c;创建一个线程是不能提高程序的执行效率的&#xff0c;所以要创建多个线程。但是多个线程同时运行的时候可能调用线程函数&#xff0c;在多个线程同时对同一个内存地…

《雅思口语真经总纲1.0》话题实战训练笔记part1——4. Fruits and vegetables

《雅思口语真经总纲1.0》笔记——第四章&#xff1a;口语素材大全&#xff08;part1、part2、part3回答准则及练习方法&#xff0c;不包括范例答案&#xff09;★★★★★ 文章目录 Fruits and vegetablesWhat kind of fruit do you like?20240723答评价 范例答案 Did you lik…

centos stream 9安装 Kubernetes v1.30 集群

1、版本说明&#xff1a; 系统版本&#xff1a;centos stream 9 Kubernetes版本&#xff1a;最新版(v1.30) docker版本&#xff1a;27.1.1 节点主机名ip主节点k8s-master172.31.0.10节点1k8s-node1172.31.0.11节点2k8s-node2172.31.0.12 2、首先&#xff0c;使用Vagrant和Virt…

前端缓存问题(浏览器缓存和http缓存)- 解决办法

问题描述&#xff1a;前端代码更新&#xff0c;但因浏览器缓存问题&#xff0c;导致页面源代码并未更新 查看页面源代码的方法&#xff1a;鼠标右键&#xff0c;点击查看页面源代码 如图&#xff1a; 解决方法&#xff1a; 注&#xff1a;每执行一步&#xff0c;就检查一下浏览…

Apache Doris 2.1.5 版本正式发布

亲爱的社区小伙伴们&#xff0c;Apache Doris 2.1.5 版本已于 2024 年 7 月 24 日正式发布。2.1.5 版本在湖仓一体、多表物化视图、半结构化数据分析等方面进行了全面更新及改进&#xff0c;同时在倒排索引、查询优化器、查询引擎、存储管理等 10 余方向上完成了若干问题修复&a…

elementplus菜单组件的那些事

在使用 elementplus 的菜单组件时&#xff0c;我发现有很多东西是官方没有提到但是需要注意的点 1. 菜单组件右侧会有一个边框 设置css .el-menu {border: 0 !important; } 2. 使用其他的 icon 文字内容一定要写在 这个 名字为 title 的插槽中 <el-menu-itemv-for"it…

@NotNull、@NotEmpty 和 @NotBlank 区别

NotNull、NotEmpty 和 NotBlank 是 Java Bean Validation (JSR 380) 规范中定义的注解&#xff0c;通常用于验证对象的属性是否满足特定的条件。这些注解常用于后端验证&#xff0c;确保接收到的数据符合预期。 NotNull 用途&#xff1a;验证一个对象是否不为null。 注意&#…

Ruby Socket 编程

Ruby Socket 编程 Socket编程是网络编程的一个基础部分,它允许程序通过网络进行通信。Ruby作为一种流行的编程语言,提供了丰富的库和接口来支持Socket编程。本文将详细介绍Ruby中Socket编程的基础知识,包括Socket的概念、如何在Ruby中创建和使用Socket,以及一些常见的Sock…

string indices must be integers

string indices must be integers 目录 string indices must be integers 【常见模块错误】 【解决方案】 常见原因及解决方法 具体案例分析 总结 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出…

Java1.1标准之重要特性及用法实例(十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列…

post方式提交中文乱码问题

post方式提交中文乱码问题 在web.xml文件添加如下代码 encodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 encodingFilter /*

kafka高性能的底层原理分析

目录 1.磁盘顺序写 2.零拷贝 3.数据压缩 4.消息批量处理 5.pageCache 6.稀疏索引 总结 Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。那么他是如何做到高性能的呢&#xff0c;本篇文章从宏观上分析一下&#xff…

C++——初识模板

前言 模板是C中的重大板块&#xff0c;是使C真正超越C语言的工具&#xff0c;在C模板没有设计出来之前其实C是没有那么被行业和社会所认可的&#xff0c;本节我们将初步了解C中的模板&#xff08;仅作大致讲解&#xff0c;具体的细枝末节将会再过几节讲解&#xff09;&#xf…

Linuxnat网络配置

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️运维工程师的职责&#xff1a;监…

王道计算机组成原理思维导图-一步到位

计算机组成原理–王道超详细版–只看它就够 https://www.processon.com/view/61036898637689719d30efe6#pc

2.2 openCv -- 如何使用 OpenCV 进行图像扫描、查找表操作及时间测量

目标 我们将寻找以下问题的答案: 如何遍历图像中的每一个像素?OpenCV中的矩阵值是如何存储的?如何度量我们算法的性能?我们的测试案例 让我们考虑一个简单的色彩缩减方法。由于使用无符号字符类型(C 和 C++)来存储矩阵中的项目,像素的一个通道可能有多达 256 种不同的值。…

centos使用scl切换软件版本时提示Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64

centos使用scl切换软件版本时提示Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64 问题原因 CentOS7的SCL源在2024年6月30日停止维护了。 当scl源里面默认使用了centos官方的地址&#xff0c;无法连接&#xff0c;需要替换为阿里云。 解决办法 1、 重命名原…

一维数组--最长平台

这道题目挺简单的&#xff0c;那你还想这么久&#xff01; 直接看代码&#xff01; #include<cstdio> long long n,a[100002],sum,b[100002],max-99999,j; int main(){scanf("%d",&n);scanf("%d",&a[1]);sum1;for(int i2;i<n;i){j;scan…

【ESP32 IDF 定时器Timer】

目录 TIM定时器介绍硬件定时器和软件定时器硬件定时器基本参数硬件定时器的操作流程初始化硬件定时器设置报警注册回调函数使能和禁用定时器启动和停止定时器硬件定时器驱动代码调试 软件定时器使用软件定时器代码编写 TIM定时器 介绍 定时器是单片机内部集成&#xff0c;可以…

Transformer模型全面解析:工作原理、应用与未来展望*

概述&#xff1a; 深入探讨Transformer模型的工作原理&#xff0c;分析其在NLP领域的应用场景&#xff0c;并展望其未来发展趋势。本文为您提供关于Transformer模型的全面指南。 正文 Transformer模型全面解析&#xff1a;工作原理、应用与未来展望 在人工智能的浪潮中&…