MySQL

77 阅读12分钟

设计数据库时一定要记得避免使用关键字

mysql

如何定位慢查询

1、使用运维工具,如skywalking,定位出现响应缓慢的接口,在定位到sql的问题

2、使用mysql自带的慢查询日志

可以在mysql的配置文件中添加如下内容

配置完后可以在var/lib/mysql/localhost-slow.log中查看记录的信息

如何分析慢sql

在select语句前加上explain或者desc关键字可以获取mysql指型查询语句的详细信息;如下

index和all的区别:

index:

  • 访问类型:全索引扫描。
  • 含义:遍历整个索引来获取数据。
  • 示例:假设有一个名为 users 的表,其中包含了 id 和 name 列,并且 id 列上存在索引。如果执行以下查询语句:

SELECT name FROM users WHERE id > 100;

  • 当查询优化器选择使用索引进行查询时,它可能会使用 index 类型,遍历索引中大于 100 的所有行,并返回相应的 name 值。

all:

  • 访问类型:全表扫描。
  • 含义:遍历整个表来获取数据。
  • 示例:继续以前面的 users 表为例,在没有适用的索引的情况下,如果执行以下查询语句:

SELECT name FROM users WHERE name LIKE '%John%';

  • 当查询优化器无法使用索引来加速查询时,它可能会选择使用 all 类型,这意味着它需要逐行扫描整个表,检查每一行的 name 值是否符合 %John% 的模式。

使用mysql自动的执行计划explain来去查看这条sql的执行情况

  • 可以通过key和key_len检查是否命中了索引,如果本身已经添加了索引,也可以判断索引是否有失效的情况
  • 可以通过type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或全盘扫描
  • 可以通过extra建议来判断,是否出现了回表的情况,如果出现了,可以尝试添加索引或修改返回字段来修复
索引概念及底层数据结构

在数据之外,数据库系统还维护着满足特定查找算法的数据结构(B+树),这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引

索引 (index)是帮助MysQL高效获取数据的数据结构(有序)。

索引主要是用来提高数据检索的效率,降低数据库的IO成本,

同时通过索引列对数据进行排序,降低数据排序的成本,也能降低了CPU的消耗。

数据结构使用B+树 原因

不使用其他的原因:

  • 无索引,全盘扫描
  • 二叉搜索树,效率提高,但是会产生二叉树退化为链表的可能
  • 红黑树,复杂度稳定为logn,但是数据量大时,树的层数太高,由于数据存储在磁盘,会使IO次数太多,效率低
  • B树,多路平衡查找树,阶数多,路径短;B+树相对于B树 1、只有叶子节点存储数据,非叶子节点只存储指针,而且叶子节点使用双向指针相连,形成双向链表,因此磁盘读写代价更低,查询效率稳定,而且便于范围查询
什么是聚簇索引和非聚簇索引,什么是回表查询

聚簇索引

聚集索引(Clustered lndex)将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据;每张表必须有,而且只有一个

选取规则:

如果存在主键,主键索引就是聚集索引。

如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。

如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引。

非聚簇索引

即二级索引(Secondary Index),它将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键,一张表可以存在多个

回表查询

通过二级索引找到对应的主键值,到聚集索引中查找整行数据,这个过程就是回表

什么是覆盖索引

覆盖索引是指 SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引;查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到。

如下: id和name字段都创建了索引

1中使用主键id查询,直接都聚集索引查询,一次查询便可得到结果

2中使用name作为条件,在辅助/二级索引中查询,可以得到id和name值,这也是覆盖索引

3需要回表查询,不是覆盖索引了

超大分页优化

利用覆盖索引,先快速定位到所需的id段,再关联查询

阿里巴巴java开发手册:

索引创建原则

1针对于数据量较大,且查询比较频繁的表建立索引。单表超过10万数据(增加用户体验)

2针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。

3尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以使用覆盖索引,节省存储空间,避免回表,提高查询效率。

4要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。

尽量选择区分度高的列作为索引,例如不要选择性别等;尽量建立唯一索引,区分度越高,使用索引的效率越高。

如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。

如果索引列不能存储NUllL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

索引失效场景

违反最左前缀法则

最左前缀法则:是指在使用复合索引进行查询时,只能从索引的最左边的列开始使用索引(由于优化器,如果使用了所有列,顺序换了也可)。

如果符合最左法则,但是跳跃了某一列,只有左边的生效。

如果违反了最左前缀原则,MySQL将无法有效地使用索引,可能会导致查询性能下降。

范围查询右边的列,不能使用索引

不要在索引列上进行运算操作,索引将失效

字符串不加单引号,造成索引失效。(类型转换)

以%开头的Like模糊查询,索引失效

sql优化经验

1、表的设计优化

2、sql语句优化

3、索引优化

创建原则、避免失效

4、主从复制、读写分离、分库分表

事务的特性

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

四大特性

原子性(Atomicity) : 事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

一致性(Consistency) : 事务完成时,必须使所有的数据都保持一致状态。

隔离性(Ilsolation): 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

持久性(Durability): 事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

举个例子:A向B转账500,转账成功,A扣除500元,B增加500元,原子操作体现在要么都成功,要么都失败在转账的过程中,数据要一致,A扣除了500,B必须增加500

在转账的过程中,隔离性体现在A像B转账,不能受其他事务干扰

在转账的过程中,持久性体现在事务提交后,要把数据持久化(可以说是落盘操作)

并发事务问题、隔离级别

并发事务会出现的问题:

脏读一个事务读到另外一个事务还没有提交的数据
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读
幻读一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 幻影

undo log和redo log

缓冲池(buffer pool) :主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),以一定频率将数据页刷新到磁盘,从而减少磁盘IO,加快处理速度

数据页(page) :是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。页中存储的是行数据

随机I/O(Input/Output)和顺序I/O是两种不同的数据读写方式,主要用于描述对存储设备(如硬盘、固态硬盘等)进行数据访问的模式。

随机I/O是指在读写数据时,访问的数据块的位置是无规律的,不按照顺序逐个访问,而是跳跃式地读取或写入数据。这种模式可能导致磁头在硬盘上频繁移动或闪存芯片在固态硬盘上寻找数据,从而增加了读写延迟和访问时间。随机I/O通常发生在随机访问、随机写入或对散布在存储设备中不连续位置的数据进行操作的场景中。

顺序I/O则是按照数据的顺序进行读写,逐个读取或写入连续的数据块。这种模式利于存储设备的预读和写入优化,可以更高效地读取或写入数据。顺序I/O通常发生在顺序读取、顺序写入或对存储设备上连续位置的数据进行操作的场景中。

redo log

重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。

该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file) ,前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用。

undo log

回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚和MVCC(多版本并发控制)。undo log和redo log记录物理日志不一样,它是逻辑日志。

  • 可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,
  • 当update一条记录时,它记录一条对应相反的update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

undo log可以实现事务的一致性和原子性

两者区别

什么是mvcc

事务的隔离性是由锁和mvcc实现的。

其中mvcc的意思是多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突,它的底层实现主要是分为了三个部分,第一个是隐藏字段,第二个是undo log日志,第三个是readView读视图

隐藏字段是指:在mysql中给每个表都设置了隐藏字段,有一个是trx_id(事务id),记录每一次操作的事务id,是自增的;另一个字段是roll_pointer(回滚指针),指向上一个版本的事务版本记录地址

undo log主要的作用是记录回滚日志,存储老版本数据,在内部会形成一个版本链,在多个事务并行操作某一行记录,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表

readView解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规则和当前的一些事务id判断该访问那个版本的数据,不同的隔离级别快照读是不一样的,最终的访问的结果不一样。如果是rc隔离级别,每一次执行快照读时生成ReadView,如果是rr隔离级别仅在事务中第一次执行快照读时生成ReadView,后续复用

主从同步原理

MySQL主从复制的核心就是二进制日志(DDL(数据定义语言)语句和 DML(数据操纵语言)语句),它的步骤是这样的:

第一:主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。

第二:从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志 Relay Log 。

第三:从库重做中继日志中的事件,将改变反映它自己的数据