一、索引
1.1 索引是什么?
官方对索引的定义为:索引是帮助MySql高效获取数据的数据结构.本质:索引是数据结构,排好序的快速查找数据结构。
1.2 索引的类型
单值索引:即一个索引只包含单个列,一个表可以有多个单列索引。
唯一索引:索引列的值必须唯一,允许有空值,查找到第一个满足条件的记录后,直接停止继续检索。
复合索引:即一个索引包含多个列。
基本语法:
CREATE [UNIQUE ] INDEX indexName ON mytable(columnName(length);
ALTER mytable ADD [UNIQUE ] INDEX [indexName] ON(columnname(length));
DROP INDEX [indexName] ON mytable;
SHOW INDEX FROM table_ name
1.3 需要与不需要用索引
需要建立索引:
1.主键自动创建唯一索引。
2.频繁作为查询条件的字段需要建立索引。
3.查询中与其他表关联的字段,外键关系建立索引。
4.查询中排序的字段。
5.查询中统计或者分组字段。
不需要建立索引:
1.表记录太少。2.经常增删改的表。
3.数据重复且分布平均的表字段,某个数据列包含许多重复的内容,建立索引就没有太大效果。
4.频繁更新的字段不适合创建索引。
5.Where条件里用不到的字段不创建索引。
1.4 索引结构
![](https://i-blog.csdnimg.cn/blog_migrate/29039f7c595a7c08300848b6f050b166.png)
![](https://i-blog.csdnimg.cn/blog_migrate/212a4673c5b7ac16b794026a9839f740.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ba9704d3cc6b980112e93a6cef858994.png)
1.5 EXPLAIN索引分析
Mysql Query Optimizer(查询优化器):Mysql中有专门负责优化SELECT语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供他认为最优的执行计划(他认为最优的数据检索方式,但不见得是DBA认为是最优的,这部分最耗费时间)。
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句、从而知道MySQL是如何处理你的SQL语句的、分析查询语句或是表结构的性能瓶颈。
EXPLAIN + SQL语句,查看执行计划包含的信息:id、select_ type、table 、 type、 possible_ keys 、 key 、 key_ len 、 ref、 rows 、 Extra。
id
select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。id相同,执行顺序由上至下;id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行。
select_ type
查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询。
![](https://i-blog.csdnimg.cn/blog_migrate/351e0af75911f40fabc6904527ea5765.png)
type
显示查询使用了何种类型,从最好到最差依次是:system > const > eq_ ref > ref > range > index > ALL.
![](https://i-blog.csdnimg.cn/blog_migrate/35db5ce02d73d01283032f278b46aa96.png)
possible_ keys
显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
key
实际使用的索引。如果为NULL,则没有使用索引。
1.6 怎么避免索引失效?
1.全值匹配。
2.最佳左前缀法则,指查询从索引最左前列开始并且不跳过索引中的列(带头大哥不能死,中间兄弟不能断)
3.不在索引列上做任何操作(计算、函数、类型转换),会导致索引失效。
4.存储引擎不能使用索引中范围条件右边的列。><这样大于小于和between and(区间判断)虽然不会让该索引字段失效,但是会导致后续的其他索引字段失效。
5. mysql在使用不等于 (!=或者<>) 的时候无法使用索引会导致全表扫描。
6.is null ,is not null 也无法使用索引。
7.like以通配符开头('%abc...')mysq|索引失效会变成全表扫描的操作。
8.字符串不加单引号索引失效
9.少用or,用它来连接时会索引失效
二、存储引擎以及索引结构差异
![](https://i-blog.csdnimg.cn/blog_migrate/0842fac5116e8a20d310da3ffd5030fa.png)
2.1 “聚簇索引”InnoDB
InnoDB的主键索引与行记录是存储在一起的,叫做聚集索引。
InnoDB: 其数据⽂件本身就是索引⽂件。相⽐MyISAM,索引⽂件和数据⽂件是分离的,其表数据⽂件本身就是按B+Tree组织的⼀个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据⽂件本身就是主索引。
2.2 “⾮聚簇索引”MyISAM
MyISAM的索引与行记录是分开存储的,叫做非聚集索引。
MyISAM: B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,⾸先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。
三、事务
事务(transaction) 是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一一个操作失败,事务也不成功。如果所有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消。
SET SESSION TX_ISOLATION='隔离级别'; #设置级别
3.1 事务的四大特性
3.1.1 原子性
即不可分割性,事务要么全部被执行,要么就全部不被执行。
3.1.2. 一致性
使数据库从一个一致性状态变换到另一个一致性状态,在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
3.1.3 隔离性
在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务
3.1.4 持久性
指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的。事务正确提交后,其结果将永久保存在数据库中
3.2 并发事务存在问题
3.2.1 脏读
一句话,读到其他事务修改了未提交的数据
3.2.2 不可重复读
指在⼀个事务内多次读同⼀数据。在这个事务还没有结束时,另⼀个事务也访问该数据。那么,在第⼀个事务中的两次读数据之间,由于第⼆个事务的修改导致第⼀个事务两次读取的数据可能不太⼀样。这就发⽣了在⼀个事务内两次读到的数据是不⼀样的情况,因此称为不可重复读。
3.2.3 幻读
幻读与不可重复读类似。它发⽣在⼀个事务(T1)读取了⼏⾏数据,接着另⼀个并发事务(T2)插⼊了⼀些数据时。在随后的查询中,第⼀个事务(T1)就会发现多了⼀些原本不存在的记录,就好像发⽣了幻觉⼀样,所以称为幻读.
3.2.4 丢失修改
指一个事务读取一个数据时,另一个事务也访问了该数据。那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。
不可重复读和幻读区别:
不可重复读的重点是修改⽐如多次读取⼀条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除⽐如多次读取⼀条记录发现记录增多或减少了。
3.3 事务隔离级别
3.3.1 READ-UNCOMMITTED(读取未提交)
最低的隔离级别,允许读取尚未提交的数据变更,什么都解决不了。
3.3.2 READ-COMMITTED(读取已提交)
允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣。
3.3.3 REPEATABLE-READ(可重复读)
对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。
3.3.4 SERIALIZABLE(可串⾏化)
最⾼的隔离级别。所有事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,该级别可以防⽌脏读、不可重复读以及幻读
3.4 MVCC 多版本并发控制
MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。可以认为是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本。
3.4.1 MVCC作用
在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。
3.4.2 当前读
它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁);
3.4.3 快照读
即不加锁的非阻塞读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;
四、bin & redo & undo 日志
先写日志还是先写数据?先写日志,为保证数据库的可恢复性,日志文件能够用来进行事务故障恢复、系统故障恢复,并能够协助后备副本进行介质故障恢复。
4.1 bin log
bin log是记录所有数据库表结构变更的二进制日志
--例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)。
作用:可以用于数据丢失后的实时备份,与master/slave主从复制结合。
4.2 redo log
用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。
作用:在实例和介质失败时,redo log文件就能派上用场,如数据库掉电,InnoDB存储引擎会使用redo log恢复到掉电前的时刻以此来保证数据的完整性。
作用:确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的持久性这一特性。
4.3 undo log
保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。
事务执行完毕的标志是写完redo log和undo log。如果在写redo log时候断电,事务就没有执行完毕。这样事物就失败了,会根据undo log回滚到事物之前
redo log和bin log的区别?
1.redo log属于存储innoDB层面,bin log属于MySQL Server层面的,这样在数据库用别的存储引擎时可以达到一致性要求。
2.redo log是物理日志,记录该数据页更新的内容;bin log是逻辑日志,记录的是这个更新语句的原始逻辑。
3.redo log是循环写,日志空间大小固定;bin log是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。
4.bin log可以作为恢复数据使用,主从复制搭建,redo log作为异常宕机或者介质故障后的数据恢复使用。
五、Mysql其他知识
5.1 MySQL 中有哪几种锁?
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
2.行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
3.页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般.
4.间隙锁,锁的是索引下的next指针,解决了mysql RR级别下是幻读的问题。
5.2 表的拆分
水平切分
根据表中数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。
通常情况下,我们使用取模的方式来进行表的拆分;比如一张有400W的用户表users,为提高其查询效率我们把其分成4张表users1,users2,users3,users4 通过用ID取模的方法把数据分散到四张表内Id%4+1 = [1,2,3,4] 然后查询,更新,删除也是通过取模的方法来查询。
垂直切分
垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。把大的字段拆分到另一个表,并且该表与原表是一对一的关系。
通常我们按以下原则进行垂直拆分: 1,把不常用的字段单独放在一张表、2.把text,blob等大字段拆分出来放在附表中; 经常组合查询的列放在一张表中;
5.3 Join
![](https://i-blog.csdnimg.cn/blog_migrate/22ce714a127823ec99c162c23d39d3bc.png)
5.4 SQL语句的执行过程
![](https://i-blog.csdnimg.cn/blog_migrate/67bedbe2a094fe6f42a07f358b20eb97.png)