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;在多个线程同时对同一个内存地…

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;就检查一下浏览…

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工程师进阶系列…

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;监…

一维数组--最长平台

这道题目挺简单的&#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;可以…

鸿蒙HarmonyOS开发:多种内置弹窗及自定义弹窗的详细使用指南

文章目录 一、消息提示框&#xff08;showToast&#xff09;1、导入模块2、语法3、参数4、示例5、效果 二、对话框&#xff08;showDialog&#xff09;1、导入模块2、语法3、参数4、示例5、效果 三、警告弹窗&#xff08;AlertDialog&#xff09;1、语法2、参数3、AlertDialogP…

STM32的GPIO输入输出方式设置示例

1、GPIO口做基本的输入/输出口使用时&#xff0c;输入有上拉输入、下拉输入、浮空输入&#xff08;既无上拉电阻也无下拉电阻&#xff09;3种输入方式&#xff1b;输出有开漏输出、推挽输出2种输出方式。 2、示例 &#xff08;1&#xff09;示例1&#xff1a;GPIO做输出的设置…

项目比赛经验分享:如何让即兴发言出彩

项目比赛经验分享&#xff1a;如何让即兴发言出彩 前言1. 顺势趁便法2. 词语撮要法3. 起承转合法4. 数字串连法结语 在项目管理和比赛的激烈竞争中&#xff0c;即兴发言往往成为展示个人魅力和团队精神的重要环节。如何在短时间内组织语言&#xff0c;表达清晰、有力的观点&…

基于JSP、java、Tomcat三者的项目实战--校园交易网(3)主页

前文功能的实现 技术支持&#xff1a;JAVA、JSP 服务器&#xff1a;TOMCAT 7.0.86 编程软件&#xff1a;IntelliJ IDEA 2021.1.3 x64 前文三篇登录和注册功能的实现 基于JSP、java、Tomcat、mysql三层交互的项目实战--校园交易网&#xff08;1&#xff09;-项目搭建&#xf…

Cisco路由器OSPF配置

Cisco路由器OSPF配置 本文已经迁移至 https://www.geekery.cn 本文档将详细介绍如何配置 OSPF&#xff08;开放最短路径优先&#xff09;协议&#xff0c;使用三个路由器&#xff1a;RA、RB 和 RC。一步一步说明每个路由器的配置、设置 IPv4 和 IPv6 地址的、配置OSPF 的启用以…

Cocos Creator2D游戏开发-(1)初始化设置

初心: 做一款微信或者抖音小游戏,然后发布,对于我来说这是一个新的赛道; 写这些文档的原因,记录一下自己学习过程,下次用的时候方便找 cocos creator版本: 3.8.3 当前小游戏飞机大战教程来源于: 抖音: 禅影 chanying001 源码目录: https://www.kdocs.cn/l/caLr6XCbEfPa 创建一个…

zeal 开发者离线文档工具

zeal是一款程序开发者不可或缺的离线文档查看器 下载地址 官网地址&#xff1a; windows版csdn下载(开箱即用含)&#xff1a;https://download.csdn.net/download/xzzteach/89588765 已离线 Android.docset Apache_HTTP_Server.docset Bash.docset Bootstrap_4.docset Bootst…

selenium入门超详细教程——网页自动化操作

文章目录 简介一、环境安装1.selenium安装2.安装浏览器驱动2.1 确定浏览器版本2.2 下载驱动 二、基础用法1.对页面进行操作1.1 初始化浏览器对象1.2 访问页面1.3 设置浏览器大小1.4 前进后退1.5 获取页面基础属性 2.定位页面元素3.模拟鼠标操作3.1 常用操作 4.模拟键盘操作4.1 …

测评Copilot和ChatGPT-4o从PDF创建PPT功能

关于 Copilot 由 PDF 创建 PPT&#xff0c;之前已经发过几篇文档说明&#xff1a; Copilot for Microsoft 365 现已支持从PDF创建Word和PPT Copilot读PDF文献一键生成PPT&#xff0c;吓傻了导师 Copilot一键将PDF转为PPT&#xff0c;治好了我的精神内耗 今天来测评对比 Cop…

在LabVIEW中使用Modbus

NI 提供了三种主要机制与 Modbus 设备进行接口&#xff1a;(1) 高级 OPC 服务器&#xff0c;(2) Modbus I/O 服务器&#xff0c;以及 (3) 在 NI LabVIEW 软件中通过 LabVIEW 实时或 LabVIEW 数据记录与监控控制&#xff08;DSC&#xff09;模块引入的低级 Modbus API。 LabVIE…