[MYSQL] MYSQL 优化总结

news/2024/10/6 8:35:27

0 查询变量参数

  • 查询某个参数时 select @@…

1 数据插入与导入

  • 普通插入:
  • 采用批量插入(一次插入的数据不建议超过1000条)
  • 手动提交事务
  • 主键顺序插入
  • 大批量插入:
    ​> + 如果一次性需要插入大批量数据,使用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 '/root/sql1.log' into table 'tb_user' fields terminated by ',' lines terminated by '\n';

2 主键设计与优化

  • 主键优化
  • 数据组织方式:在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表Index organized table, IOT
  • 页分裂:页可以为空,也可以填充一般,也可以填充100%,每个页包含了2-N行数据(如果一行数据过大,会行溢出),根据主键排列。
  • 页合并:当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除,并且它的空间变得允许被其他记录声明使用。当页中删除的记录到达 MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠近的页(前后)看看是否可以将这两个页合并以优化空间使用。
  • MERGE_THRESHOLD:合并页的阈值,可以自己设置,在创建表或创建索引时指定
    CREATE TABLE t1 ( id INT, KEY id_index (id) ) COMMENT='MERGE_THRESHOLD=45';
    CREATE TABLE t1 ( id INT, KEY id_index (id) ); ALTER TABLE t1 COMMENT='MERGE_THRESHOLD=40';
    CREATE TABLE t1 ( id INT, KEY id_index (id) COMMENT 'MERGE_THRESHOLD=40' );
    CREATE TABLE t1 ( id INT, KEY id_index (id) ); ALTER TABLE t1 DROP KEY id_index; ALTER TABLE t1 ADD KEY id_index (id) COMMENT 'MERGE_THRESHOLD=40';
    详情参见: Mysql主键优化之页分裂与页合并 - CSDN
    详情参见: Configuring the Merge Threshold for Index Pages - MYSQL
  • 主键设计原则:
  • 满足业务需求的情况下,尽量降低主键的长度
  • 插入数据时,尽量选择顺序插入,选择使用 AUTO_INCREMENT 自增主键
  • 尽量不要使用 UUID 做主键或者是其他的自然主键,如身份证号 (占用内存)
  • 业务操作时,避免对主键的修改

3 Order By 优化

  • Order By 优化
  • Using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区 sort buffer 中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序
  • 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;会全部走索引

  • 总结:
  • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则
  • 尽量使用覆盖索引

覆盖索引是指select的数据列只用从索引中就能够取得,不必读取数据行。换句话说,查询列要被所建的索引覆盖。

  • 多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)
  • 如果不可避免出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)

4 Group By 优化

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

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

5 Limit 优化

  • 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;

6 Count 优化

  • 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()

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

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

如以下语句:

-- 这句由于id有主键索引,所以只会锁这一行;
update student set no = '123' where id = 1;,-- 这句由于name没有索引,所以会把整张表都锁住进行数据更新,解决方法是给name字段添加索引。
update student set no = '123' where name = 'test';,

X 参考文献

  • MySQL笔记 - CSDN

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

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

相关文章

AI加持的开发平台,如何满足您的独一无二?

在数字化浪潮席卷全球的今天,软件开发平台在企业发展中的地位正变得愈发重要。作为技术创新的基石,开发平台已逐渐成为当今时代信息技术进步的中坚力量,更是推动企业技术升级、业务发展的关键所在。 而今,随着人工智能技术的飞速发展,开发平台也再次迎来新的变革。AI的加持…

VulNyx - Mail 靶机

扫描靶机 发现22 和 80端口 访问80端口 发现id=1 和2 时都会有回显dirsearch -u http://http://192.168.200.39访问这个1 和 2的路径 发现竟然和上面那个id=1和id=2的内容相同 这里就可以判断是个include漏洞了用php_filter_chain_generator-main构造伪协议链 执行rce执行反弹…

电科邮件系统短信轰炸

短信轰炸 在该页面下,只有对于学号与验证码的检测实现对于密码的找回,我的想法是对于学号的构造实现短信轰炸。因为学校中的学号构成有规律,所以可以构造不同的学号 ![](C:\Users\21094\Pictures\Screenshots\屏幕截图 2024-08-28 155947.png) 点击下一步后,可以看到该学号…

Cron表达式

Cron表达式是一种用于描述定时任务执行时间的字符串格式,在Unix、Linux、Mac OS X等操作系统中被广泛使用。它通过一系列的时间字段来描述一个定时任务应该在哪些时间点执行。 它通常由6~7位组成,年份可以省略。每个时间字段都可以是数字、星号、逗号、减号、正斜杠和问号这些…

基于 Quanto 和 Diffusers 的内存高效 transformer 扩散模型

过去的几个月,我们目睹了使用基于 transformer 模型作为扩散模型的主干网络来进行高分辨率文生图 (text-to-image,T2I) 的趋势。和一开始的许多扩散模型普遍使用 UNet 架构不同,这些模型使用 transformer 架构作为扩散过程的主模型。由于 transformer 的性质,这些主干网络表…

opc da 服务器数据 转IEC61850项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 应用条件 2 4 查看OPC DA服务器的相关参数 2 5 配置网关采集opc da数据 4 6 用IEC61850协议转发数据 6 7 网关使用多个逻辑设备和逻辑节点的方法 9 8 在服务器上运行仰科OPC DA采集软件 10 9 案例总结 12 1 案例说明在OPC DA服务器上…

电科校园邮箱系统逻辑漏洞

校园邮件系统逻辑漏洞导致邮件轰炸 邮件轰炸 首先通过自己的账号登录进入邮件系统之后,进入到信息修改的界面发现存在邮箱绑定功能,在尝试绑定自己的邮箱之后,可以看到存在提示“找回密码时可以使用备用邮箱找回”。输入邮箱密码之后进入到下一个页面在此页面完成邮箱绑定,…

基于surging 如何利用peerjs进行语音视频通话

一 、 概述 PeerJS 是一个基于浏览器WebRTC功能实现的js功能包,简化了WebrRTC的开发过程,对底层的细节做了封装,直接调用API即可,再配合surging 协议组件化从而做到稳定,高效可扩展的微服务,再利用RtmpToWebrtc 引擎组件可以做到不仅可以利用httpflv 观看rtmp推流直播,还可…