mysql优化

news2024/11/27 1:22:43

索引: 排好序的数据结构

从磁盘上拿一条记录要和磁盘做一次IO操作,,磁盘的IO性能不高

索引数据结构:

  • 二叉树(binary search tree) : 单边增长的数据没有帮助
  • 红黑树(red black tree) : 二叉平衡树,表记录很多时,树的高度过高
  • b tree : 每个索引下面都有data,导致非叶子节点不能容纳更多的索引,,树的深度比 b+树高
  • b+ tree : 数据在叶子节点上,,非叶子节点都是索引,,每个节点存数据16kb
    为什么是16kb?
    • 假设一张表主键bigint 8字节索引,
    • 存放一个元素 = 存放一个索引8字节+下一个节点的地址6字节 = 14字节
    • 16kb/14b = 1170 ,一个节点大概能放1170个元素
    • 最后一层叶子结点带数据data,假设一行记录大小为1kb,,一个叶子结点可以放16个元素
    • 如果这个树有三层,,那么1170117016=两千多万数据,,树的高度为3
      在mysql的高版本,,会将非叶子节点load到内存中

查找次数树的高度紧密相关

b+树查找: 将根节点整个节点的元素,加载到内存中,然后折半查找,,定位下一个节点的磁盘位置,,然后下一个节点加载到内存中,继续比较
在这里插入图片描述

存储引擎

存储引擎是针对数据库表的

MyISAM引擎文件:
  • ____.frm :frame ,, 数据表结构相关的信息
  • ___.MYD : MyISAM 的data
  • ___.MYI : MyISAM的index

___.MYI: 会将b+树组织好,从根节点开始遍历,,叶子结点的data放的是 索引所在行的磁盘文件地址,然后根据这个地址,再去___.MYD去定位具体的数据行

InnoDB文件:
  • ___.frm : 表结构信息
  • ___.ibd : 所有数据,也是按照b+树来组织的,,,叶子节点存放的是 索引所在行的其他列的数据

MyISAM的主键和非主键索引都是非聚集索引
InnoDB只有一个聚集索引,是主键,,,非主键索引存放的是聚集索引的索引值
为什么非主键索引不存data?

  • 节约空间
  • 数据一致性

名词

聚集索引 : 叶子节点包含整个完整的数据记录,,InnoDB的主键索引就是聚集索引,,或者说是聚簇索引

非聚集索引: MyISAM引擎的主键索引就是非聚集索引,,他的叶子结点,,只包含了data的地址,,没有数据,,,索引和数据分开存储的叫非聚集索引

联合索引: 多个字段共成一个索引,一张表不推荐你建立多个单值索引,两到三个联合索引搞定

索引下推: 5.6之后mysql引入的一个索引优化,,联合索引过滤,,每过滤一条数据,,比较剩下两个索引,,比较完了之后过滤掉数据,,这个过滤完的结果集非常小,然后去回表

文件排序:分为单路排序,双路排序

  • 如果sort_buffer设置比较小,,使用双路排序,,,需要回表
  • 如果sort_buffer设置比较大,可以单路排序,不用回表

问题

为什么InnoDB必须建一个主键?

  • __.ibd文件,这些数据必须用一个b+树来组织,如果你没有主键,,mysql会从你的这张表中选择一列数据都不相等的作为主键,,如果没有这样一个列,mysql会给你建一个隐藏列,,来组织你整个表的数据

为什么推荐整形自增作为主键?

  • 整形比大小 和 字符串比大小,,整形比大小更快
  • 整形比字符串大小 小很多,占用空间小,,一个节点上可以容纳更多的元素
  • 因为是b+树,,从中间插入元素,会导致树的分裂和平衡,,自增会在末尾插入

为什么不用哈希索引?
mysql底层有自己的哈希算法

  • 哈希冲突
  • 哈希只能等值查询,不能范围查找,没有比大小的概念

为什么 大于 不用索引下推?

  • 索引下推,当你查完第一个还要比较后面的联合索引,,结果集比较小的情况下会使用,,大于是个范围不固定

sql优化

explain
在这里插入图片描述
explain中的列:

  • partitions : 这张表是否用分区
  • select_type :
    • simple : sql语句比较简单,没有子查询,关联查询
    • derived : 衍生的,在from之后的查询生成出来的临时表,叫衍生表
    • subquery: 在select后面查出来的表
    • primary : 复杂查询,他的查询要关联其他好几个查询
  • table :数据从哪里来的,比如:derived3(衍生表id为3)
  • id : 执行顺序,id越大,,优先执行,id出现相等,谁排在前面,谁先执行
  • type : sql的访问类型
    type为null,执行的sql不一定会查表和数据,比如数据有序排列,就能直接找到min()最小值,不会去扫描表,,在索引优化的时候就拿到结果
    • system : 从一张表查询,查的那张表本身就只有一条记录
    • const : sql查询条件是主键,是唯一索引,查找就像找一个常量一样
    • eq_ref : 当前表用主键关联(唯一键),仅次于const
    • ref : 你这个查询条件没有用唯一键(主键)去查,,但是还是会用到索引,但不是唯一索引,是普通索引,有可能查出多条结果集,,也有可能是唯一索引的部分前缀
    • range : 范围查找
    • index : 扫描全索引拿到结果集,,这个索引是指二级索引
    • all : 扫描全部索引拿到结果集,,这个索引是指 聚簇索引
  • possible_key : 可能会用到的索引
  • key : 真正执行的时候用的索引
  • key_len : 可以知道用了哪几个索引
    • 如果是utf-8,一个数字或者一个字母占一个字节,一个汉字三个字节char(n)就是3n字节,,varchar(n):就是3n+2字节,,加的2字节是用来存储字符串的长度,因为varchar是可变字符
    • tinyint:1字节,,smallint:2字节,,,int:4字节,bigint:8字节
    • date:3字节,datetime:8字节,timestamp:4字节
      索引最大长度是768字节,当字符串过长时,,mysql会将前半部分字符提取出来做索引
  • ref: 这个索引关联查询的那个字段
  • extra :
    • using index: 使用覆盖索引,你查询的字段在索引树中全部包含了,不用回表
    • using where : 使用了where,并且没有用到索引
    • using index condition : 查询的列不完全被索引覆盖,,比如:联合索引只使用了其中一个并且这一个使用了范围查找索引失效
    • using temporary: 使用临时表,效率不高,,比如:distinct去重,,如果查找的字段没有索引,,就会把所有结果弄到临时表中,在临时表去重,,如果有索引,就可以直接将数据取出来,,因为索引是排好序的,去重操作,可以用索引去重
    • using filesort : 在排序的时候,,如果order by 后的字段没有索引,就会将结果集放在内存中,如果数据量大放磁盘,,再排序,,如果order by后的字段有索引,使用索引排序

查询的结果集在 主键索引 和 二级索引 都有,会优先扫描小的索引,,type为index,或者all,,相当于 叶子结点从左往右一直去扫,,遍历整个索引


cost成本计算:
trace工具 : 分析执行计划为什么这么走


数据量太少了,没必要走索引,还需要回表,不如全表扫描
like: 不管表大,还是表小,都会走索引
in 或者 or : 表大走索引,,表小,不走


mysql维护自己的总行数:
对于MyISAM 引擎来说,总行数会被存储到磁盘上
对于InnoDB来说,,count需要实时计算
解决:

  • show table status 查出rows大概条数
  • 写到redis里面
  • 整个数据库表来记录它有多少条

mysql优化

  1. 不要在索引列上做任何操作(计算,函数,手动或者自动类型转换),会导致索引失效
  2. or有很多的话,会导致 索引树要扫很多次,,还不如全表扫描
  3. 一个大范围查找,数据量太多了,还不如全表扫描快一些
    • 解决: 拆分成多个小范围
  4. 尽量使用覆盖索引,,减少select * 语句
  5. mysql在使用不等于(!= 或者 <>) ,not in ,not exists 的时候无法使用索引
  6. is null ,is not null 一般情况下不能使用索引
  7. like 通配符开头,索引失效
  8. 关联字段加索引,,让mysql做join操作的时候尽量选择NLJ算法(嵌套循环连接)
  9. 小表驱动大表,写多表连接sql是明确知道哪张表是小表可以使用straight_join连接,省去mysql优化器自己判断的时间
# t2 是小表:  `过滤`完成之后,参与join的总数据量最小的那个表
select * from t2 straight_join t1 on t2.a = t1.a
  1. in 是先执行里面,里面是小表,exists先执行外面,外面是小表
  2. exists往往用join代替
  3. 如果整型数据没有负数,如ID,建议指定为UNSIGNED无符号类型,容量扩大一倍
  4. 建议使用tinyint 代替 enum,bitenum,set
  5. 避免使用整数的显示宽度,,也就是说int(10),直接用int
  6. decimal最适合保存准确度要求高,而且用于计算的数据
  7. 整数通常是最佳数据类型,因为速度快,并且能auto_increment
  8. 关联的那张大的表,一定要走索引,被驱动的表必须走索引
  9. join表最多不超过3张
  10. count(字段) 会将那个字段拿到内存,最后统计内存有多少个。。count()不会将*读取到内存中,,,count()会计算null值,,count(列名)不会计算null
  11. 单表超过500w,超过2GB,分库分表
  12. 严禁左模糊,和全模糊,,走搜索引擎
  13. in 能避免就避免,,in里面的数据不能太多,,控制在1000以内
  14. 禁止使用存储引擎
  15. 使用编码utf-8,如果存储表情,使用utf8m64,笑脸表情–》4个字节

怎么设计索引:

  • 代码先行,索引后上
  • 联合索引,尽量覆盖你要查询的sql语句,尽量建联合索引,,唯一索引可以建,规避字段重复,,考虑 where,order by,group by 是否最左前缀
  • 不要在小基数上建立索引,没有意义,,做一个distinct的结果很小,如sex
  • 几百个字符建索引varchar(255),对于这种比较长的字段,可以建一个前缀索引key index(name(20),age,position),这样之后order by,group by 不能使用,,,大部分情况下前面20个字符的区分度已经很高了
  • 慢sql,,mysql默认慢sql为10s,,会将sql写在文件里,自己分析,是否走索引set global long_query_time=4修改慢sql时间,开启mysql慢查询会影响性能
  • 范围查找之后不会走索引,,尽量建在最后面
  • 对于基数比较小的,,又是索引,,又要使后面的索引生效可以使用 sex in (所有可能) 使用in,,in在大数据量下走索引
  • 如果有多个范围,都需要被索引,,可以将其中一个返回变成一个确定的值,,比如 查找最近7天的用户 变成 是否活跃,,添加索引,,再搞一个定时任务,去刷新这个是否活跃 字段
  • 如果有特殊需求,可以新建其他的联合索引
  • 尽量通过1-2个复杂的多字段联合索引,将80%的场景覆盖掉,然后用1-2个辅助索引尽量抗下剩余的20%

数据类型的选择:
小数用decimal,定长char ,不定长varchar
datetime : 8字节 范围1000-9999
timestamp : 4字节 范围 1970-2038 : 小公司用timestamp

阿里要求一张表必须具备三个字段 id,create_time,modify_time
char(n) : 存数据的时候,会在后台,用空格补充,,查询的时候又将空格去掉,不影响查询
varchar(n) : 最大列长度

能确定长度的就用char。
想blob和 text, 占用空间比较大的,推荐单独存入一个表,,用主键关联

优化场景

分页
select * from employees limit 10000,10

表示从employees表中读取10010条记录,,然后抛弃前面10000条,然后读到后面10条,如果查询一张大表比较靠后的数据,执行效率非常低


select * from employees order by name limit 90000,5

虽然走了name索引,但还是会全表扫描,不用回表
优化:

select * from employees e inner join (select id,name from emplyees order by name limit 90000,5) ed on e.id=ed.id

将全表扫描变成了 全表扫二级索引,,扫出来的数据很小,然后在和 employees表关联,,关联用的索引,也很快

mysql表关联常见的两种算法

嵌套循环连接算法 Nested_Loop Join(NLJ)

读取驱动表,每一次读取一行,,然后根据相关联的字段去另一张表(被驱动表)中取出满足条件的行

使用了NLJ算法,,一般join语句中,如果执行计划Extra中未出现using join buffer则表示join算法是 NLJ

如果被驱动表的关联字段没有索引,,使用NLJ算法性能会比较低

基于块的嵌套循环连接算法Block Nested_Loop Join (BNL)

把驱动表读取到 join_buffer 中,,被驱动表的每一行和驱动表中所有数据依次做对比,
如果驱动表很大的话,join_buffer_size 默认256k,,放不下驱动表数据的话,就会分段放,,然后执行完第一个块的记录之后,清空join_buffer,将剩余的驱动表数据加载进去,,继续比较

为什么要选择BNL而不用NLJ

NLJ是磁盘扫描
BNL磁盘扫描次数很少,,相比于磁盘扫描,BNL内存计算会快很多

总结

  1. b+树叶子节点有双向指针,叶子节点从左到右排好序,,,如果范围查找的数据量很大,会很慢

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

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

相关文章

YOLOv1-YOLOv7全系列解析汇总

导读 目标检测Yolo算法是非常经典且应用广泛的算法&#xff0c;而在Yolo中&#xff0c;又分成了输入端、网络推理、输出层&#xff0c;每个部分都可以延伸出很多的优化方式&#xff0c;本文主要从Yolov1~v7各个版本的Backbone&#xff0c;Neck&#xff0c;Head&#xff0c;Tri…

JSPM基于SSM的乐聘网人才招聘系统

开发工具(eclipse/idea/vscode等)&#xff1a;idea 数据库(sqlite/mysql/sqlserver等)&#xff1a;mysql 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;主要功能模块 &#xff08;核心功能完整&#xff0c;不局限于下面我想的功能&#xff0c;下面的功能可以改&…

LeetCode刷题总结文档

前言 本文的刷题顺序依照代码随想录进行&#xff0c;因此题目板块的划分也和代码随想录一致。每个版块我会按照以下内容进行组织&#xff1a; 该类型题目的特征时间复杂度值得一讲的相关题目知识 正文 数组 二分查找 特征&#xff1a;有序数组中找特定组合的快速查询方法…

如何查询域名是否备案,域名备案批量查询方法

所有备案的域名都是需要通过工信部审核&#xff0c;录入到系统才可正式使用&#xff0c;所以我们在工信部的网站查询域名是否由备案信息就可以辨别出此域名是否有备案了。但是&#xff0c;大多数站长少则几十个域名&#xff0c;几千几万域名也是有的&#xff0c;如果还是在工信…

kong网关使用记录

kong 是一个api网关&#xff0c;类似nginx的网关&#xff0c;一般用于api服务的管理 kong 可以从consul中通过dns获取服务路由&#xff0c;可以自动实现负载均衡 kong kong最新版没有了conteos的安装文档&#xff0c;现在用Ubuntu来安装kong 1 下载kong curl -Lo kong-enter…

ERROR: Failed building wheel for box2d-py 解决方法

当我们在一个全新的Python环境中构建一个AI/ML项目时&#xff0c;往往会在pip install -r requirements.txt阶段遇到这样一个错误&#xff1a; Building wheel for box2d-py (setup.py) ... error .... swig.exe -python -c -IBox2D -small -O -includeall -ignoremissing -w2…

Java中常见的注解

一、注解 二、三种JDK内置的基本注解 1、Override 表示该方法是重写的父类方法。 为什么要写Override&#xff1f; 其实方法前不写Override是ok的&#xff0c;并且仍然是重写了父类方法。However&#xff01;如果方法前有Override注解&#xff0c;编译器就会去检查该方法是否真…

ToB SaaS公司如何低成本高效获客

今年SaaS行业有些冷&#xff0c;如何过冬成了热门话题。原来天天对外讲帮客户降本增效&#xff0c;现在自个儿降本增效。调整组织架构&#xff0c;精简人员&#xff0c;砍预算&#xff0c;大抵都要来一遍。隔三岔五听说某家公司裁员&#xff0c;某家公司工资减半。市场预算自然…

CSS基础总结(一)

文章目录 一、CSS概述 &#xff08;1&#xff09;简介 &#xff08;2&#xff09;语法规范 &#xff08;3&#xff09;代码风格 二、CSS基础选择器 &#xff08;1&#xff09;标签选择器 &#xff08;2&#xff09;类选择器 &#xff08;3&#xff09;多类名选择器 &am…

STM32F103xx随记

关于STM32F103xx单片机的一些零碎知识&#xff0c;随时整理下来&#xff0c;方便查阅。 STM32F103xx随记STM32 & STM8 命名STM32F103xx引脚定义表引脚信息芯片手册地址大佬那里抄来的图STM32F103xxADC笔记STM32 & STM8 命名 STM32F103xx引脚定义表 今天在给新的模块添…

直播弹幕系统(二)- 整合RabbitMQ进行消息广播和异步处理

直播弹幕系统&#xff08;二&#xff09;- 整合RabbitMQ进行消息广播和异步处理前言一. Socket服务整合RabbitMQ二. 弹幕服务创建2.1 创建一个公共maven项目2.2 弹幕服务项目创建2.2.1 创建队列和广播型交换机2.2.2 生产者发送最终弹幕数据2.2.3 消费者监听原始弹幕数据2.3 Soc…

安卓11上的存储权限问题

这篇文章&#xff0c;想来发布的有些晚了&#xff0c;安卓11已经发布多时了&#xff0c;关于安卓11上的存储权限变更的文章数不胜数&#xff0c;所以这篇文章只做为自己的一个简单的记录吧&#xff01; 在说11之前&#xff0c;我们先回忆以下10上存储权限的变更&#xff1a;每…

GaiaX开源解读 | 给Stretch(Rust编写的Flexbox布局引擎)新增特性,我掉了好多头发

GaiaX&#xff08;盖亚&#xff09;&#xff0c;是在阿里文娱内广泛使用的Native动态化方案&#xff0c;其核心优势是性能、稳定和易用。本系列文章《GaiaX开源解读》&#xff0c;带大家看看过去三年GaiaX的发展过程。 GaiaX的布局方案 - Flexbox 阿里文娱业务作为一个内容分发…

Linux调试器——gdb

gdb什么是gdbdebug与releasegdb的基本操作查看代码与断点执行与调试监视变量什么是gdb 之前用的一直都是VS编译器进行调试&#xff0c;调试是一个非常重要的过程&#xff0c;在Linux中调试需要用到一个工具就是gdb。 在调试思路上VS编译器和gdb是一样的&#xff0c;但是调试过…

【云原生进阶之容器】第一章Docker核心技术1.5.1节——cgroup综述

1. cgroups概述 1.1 为什么需要cgroup 在Linux里,一直以来就有对进程进行分组的概念和需求,比如session group, progress group等,后来随着人们对这方面的需求越来越多,比如需要追踪一组进程的内存和IO使用情况等,于是出现了cgroup,用来统一将进程进行分组,并在分组的…

51单片机——静态数码管实验,小白讲解

数码管介绍&#xff1a; 数码管是一种半导体发光器件&#xff0c;其基本单元是发光二极管。数码管也称LED数码管&#xff0c;不同行业人士对数码管的称呼不一样&#xff0c;其实都是同样的产品。数码管按段数可分为七段数码管和八段数码管&#xff0c;八段数码管比七段数码管多…

中国计算机大会CNCC【笔记】

中国计算机大会CNCC【笔记】前言推荐中国计算机大会CNCCCNCC 青年精英思想秀主题&#xff1a;当呼吸化为空气——物联网安全云原生一站式数据管理与服务 : 构建云计算数据平台生态计算产业未来应用场景与创新方向展望用开源打造云原生数据库的生态系统CCF 优博的培养与成长最后…

华为HI第二款车,阿维塔11的智能化有什么特点?

作者 | 德新 编辑 | 于婷阿维塔11&#xff0c;这款车不用过多介绍&#xff0c;长安 x 宁德 x 华为 3家联合打造。外观独特&#xff0c;在宝马17年的顶尖设计师Nader Faghihzadeh主导的设计&#xff1b;用料也很足&#xff0c;90度 - 116度的电池&#xff0c;34.99万的起售价&am…

利用 ALV 实现增删改查系列之一:让 ALV 报表进入可编辑状态试读版

在 CSDN 和我的知识星球里有朋友向我提出同样的问题&#xff0c;询问如何在 ALV 里实现增删改查操作。 虽然需求只有一句话&#xff0c;但是这个需求背后涉及到的知识点不少&#xff0c;因此笔者会通过几篇文章的篇幅&#xff0c;来介绍这个需求的详细实现步骤。 本文先解决第…

【Linux学习】之访问命令行

【Linux学习】之访问命令行 文章目录【Linux学习】之访问命令行一、基础知识二、练习1.使用 date 命令来显示当前的日期和时间。2.以12小时制显示当前时间(例如&#xff0c;11:42:11AM)。3. 查看/home/student/zcat 的文件类型&#xff0c;是否被人读取?4.使用wc命令和 Bash 快…