【MySQL】SQL优化

2023-09-19 10:21:23

SQL 优化

插入数据

普通插入:

  1. 采用批量插入(一次插入的数据不建议超过1000条,500 - 1000 为宜)
  2. 手动提交事务
  3. 主键顺序插入(主键顺序插入的效率大于乱序插入)

大批量插入: 如果一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令插入。

# 客户端连接服务端时,加上参数 --local-infile(这一行在bash/cmd界面输入)
mysql --local-infile -u root -p
# 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
set global local_infile = 1;
select @@local_infile;
# 执行load指令将准备好的数据,加载到表结构中,先要把表建立起来。
load data local infile '/home/jerry/load_user_100w_sort.sql' into table tb_user fields terminated by ',' lines terminated by '\n';

主键优化

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

主键的顺序的插入过程如下:

在这里插入图片描述

但是如果主键是乱序插入的话,就会导致需要插入的位置为中间的位置,会有页分裂的过程。

页分裂:页可以为空,也可以填充一般,也可以填充100%,每个页包含了2-N行数据(如果一行数据过大,会行溢出),根据主键排列。

比如下图插入50后溢出,会开辟一个新的页(页分裂),第1页的前50%不动,后50%转入第三页与新的数据合并,并修改链表指针。

在这里插入图片描述

页合并:当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。当页中删除的记录到达 MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠近的页(前后)看看是否可以将这两个页合并以优化空间使用。

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

文字说明不够清晰明了,具体可以看视频里的PPT演示过程:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=90

主键设计原则:

  • 满足业务需求的情况下,尽量降低主键的长度,二级索引的叶子节点保存的就是主键,所以主键小占用的空间也就会少。
  • 插入数据时,尽量选择顺序插入,选择使用 AUTO_INCREMENT 自增主键
  • 尽量不要使用 UUID 做主键或者是其他的自然主键,如身份证号,占用的空间大。
  • 业务操作时,避免对主键的修改

order by优化

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

如果order by字段全部使用升序排序或者降序排序,则都会走索引,但是如果一个字段升序排序,另一个字段降序排序,则不会走索引,explain的extra信息显示的是Using index, Using filesort,如果要优化掉Using filesort,则需要另外再创建一个索引,如:create index idx_user_age_phone_ad on tb_user(age asc, phone desc);,此时使用select id, age, phone from tb_user order by age asc, phone desc;会全部走索引

在这里插入图片描述

总结:

  • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
  • 尽量使用覆盖索引
  • 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
  • 如果不可避免出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)

group by优化

  • 在分组操作时,可以通过索引来提高效率
  • 分组操作时,索引的使用也是满足最左前缀法则的

如索引为idx_user_pro_age_stat,则句式可以是select ... where profession order by age,这样也符合最左前缀法则

limit优化

常见的问题如limit 2000000, 10,此时需要 MySQL 排序前2000000条记录,但仅仅返回2000000 - 2000010的记录,其他记录丢弃,查询排序的代价非常大。 优化方案:一般分页查询时,通过创建覆盖索引能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化

例如:

-- 此语句耗时很长
select * from tb_sku limit 9000000, 10;
-- 通过覆盖索引加快速度,直接通过主键索引进行排序及查询
select id from tb_sku order by id limit 9000000, 10;
-- 下面的语句是错误的,因为 MySQL 不支持 in 里面使用 limit
-- select * from tb_sku where id in (select id from tb_sku order by id limit 9000000, 10);
-- 通过连表查询即可实现第一句的效果,并且能达到第二句的速度
select * from tb_sku as s, (select id from tb_sku order by id limit 9000000, 10) as a where s.id = a.id;

count优化

MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count() 的时候会直接返回这个数,效率很高(前提是不适用where);
InnoDB 在执行 count(
) 时,需要把数据一行一行地从引擎里面读出来,然后累计计数。
优化方案:自己计数,如创建key-value表存储在内存或硬盘,或者是用redis

count的几种用法:

  • 如果count函数的参数(count里面写的那个字段)不是NULL(字段值不为NULL),累计值就加一,最后返回累计值
  • 用法:count(*)、count(主键)、count(字段)、count(1)
  • count(主键)跟count()一样,因为主键不能为空;count(字段)只计算字段值不为NULL的行;count(1)引擎会为每行添加一个1,然后就count这个1,返回结果也跟count()一样;count(null)返回0

各种用法的性能:

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

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

update优化(避免行锁升级为表锁)

InnoDB 的行锁是针对索引加的锁,不是针对记录加的锁,并且该索引不能失效,否则会从行锁升级为表锁。

如以下两条事务已开启还未提交的语句: update student set no = '123' where id = 1;,这句由于id有主键索引,所以只会锁这一行;
update student set no = '123' where name = 'test';,这句由于name没有索引,所以会把整张表都锁住进行数据更新,此时并发性能降低。解决方法是给name字段添加索引,就可以由表锁变成行锁。

更多推荐

打造本地紧密链接的开源社区——KCC@长沙开源读书会&openKylin爱好者沙龙圆满举办...

2023年9月9日,由开源社联合openKylin社区举办的KCC@长沙开源读书会&openKylin爱好者沙龙,在长沙圆满举办。这是KCC@长沙首次正式进入公众视野,开展开源交流活动,也是openKylin社区长沙首场线下沙龙。长沙地区及其周边的众多开源爱好者齐聚活动现场,聆听读书分享、参与开源话题讨论,实现1+1>

HAM高可用配置及故障切换

1.什么是MHAMHA(MasterHighAvailability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA的出现就是解决MySQL单点的问题。MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可

RK3588修改eth0和eth1,对调这两个网卡设备的名称

1、以太网卡的名称一般是ethX(X可以是0,1,2,3…),一般我们的设备只有一个网卡,并且一般也不会改变它的网卡名称,所以不需要关注此问题,但是有一些设备有两三个网卡,有时候我们需要eth0是指定的硬件网卡设备,此时我们就需要人为干预一下,修改一下网卡的名称,使其满足我们的使用场景。2、在rk平台,假如你的两个网卡

蓝蓝设计提供地理信息系统GIS界面设计

北京蓝蓝设计(北京兰亭妙微科技有限公司)是一家专业的设计公司,致力于为客户打造卓越的用户体验和品牌价值。他们在地理信息系统(GIS)UI界面设计领域拥有丰富的经验和专业的设计团队。他们深入了解地理信息系统的特点和用户需求,通过用户研究和数据分析,精心设计出符合用户习惯和心理的GISUI界面。他们注重界面的布局和排版,确

软文发稿:软文发稿小技巧让你瞬间爆红

欢迎阅读本篇科普文章,我们将为您介绍软文发稿推广的小技巧,帮助您快速在网络平台上获得广泛关注。不仅仅是吸引眼球,我们还将分享实用的策略,帮助您提高软文的质量,提升传播效果。1.精准抓住受众要瞬间爆红,首先要明确目标受众。在撰写软文之前,进行市场调研是必不可少的步骤。了解受众的年龄、性别、兴趣爱好、需求等信息,有助于您编

深圳企业智荟康亮相深圳教装展,大力推动校园健康午休工程

2023年9月15日上午,第五届深圳教育装备博览会在深圳(福田)会展中心隆重开幕。本届教博会以“数字赋能·先行示范”为主题,这场盛会吸引了来自全国各地的众多教育界人士和专业观众。主办方介绍,本次展会将有效推动教育装备领域的技术革新和产业升级,将继续引领行业风向,加速促进产业融合,为各级各类教育机构和教育装备企业提供新技

Python爬虫技术系列-01请求响应获取-urllib库

Python爬虫技术系列-01请求响应获取-urllib库1urllib库1.1urllib概述1.1.1urllib简介1.1.2urllib的robotparser模块1.1.3request模块1.1.4Error1.1.5parse模块1.2urllib高级应用1.2.1Opener1.2.2代理设置1urll

2023常用的原型设计软件推荐

美观易操作的产品原型可以帮助团队构建积极的用户体验,帮助团队理解产品交互逻辑。因此,可互动、易修改的产品原型设计对产品的点击率和回访率具有重要意义。选择专业的产品原型设计工具,可以为团队和企业带来高效的产品设计体验。本文选择了四种产品原型设计工具,可以为实际工作带来方便。让我们看看。即时设计即时设计是国内首款专业级的U

SpringBoot

SpringBoot1.概念和介绍Spring用于简化Java程序的开发,而SpringBoot为了简化Spring程序开发。SpringBoot是Spring脚手架。可以快速完成Java程序的创建、提高开发效率等。SpringBoot的优点:快速集成框架,提供启动依赖的功能,可以集成各种框架。内置了运行容器、无需配置

酷开科技,让家庭娱乐生活充满激情

近几年,随着智能电视在家庭生活中的广泛应用,让人们的家庭娱乐生活有了更多的选择,但随之而来的是消费者的需求也在不断地升级,个性化、细分化的需求趋势越加凸显。而酷开科技正是抓住了这个机遇,不断赋能家庭娱乐生活场景,获得了更多消费者的青睐。与此同时,酷开科技凭借自身包容的开放生态体验,以及为消费者提供更丰富、更多元的内容,

C++实现观察者模式(包含源码)

文章目录观察者模式一、基本概念二、实现方式三、角色四、过程五、结构图六、构建思路七、完整代码观察者模式一、基本概念观察者模式(又被称为模型(Model)-视图(View)模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供

热文推荐