参考大庆指针面试宝典和xiaolincoding.com
优质文章
MySQL 可重复读隔离级别,完全解决幻读了吗? | 小林coding (xiaolincoding.com)
1.请说一下对MySQL架构的了解?
架构图
预处理阶段的语法树的结构
具体而言MySQL架构可以分为Server层和存储引擎层俩部分
Server层
连接器
用于建立客户端于服务器之间的连接,相当于客户端获取到了数据库的管理权限
查询缓存
一个SQL语句首先会到缓存中查看这条语句之前是否被查询过(如果开启了查询缓存功能),如果查询过直接返回缓存中的结果给客户端。
该机制的优点是如果命中的话,效率很高。缺点是缓存失效的频率太高,只要表一进行更新,该表的所以查询缓存都会被清空,因为该缺点,MySQL 8.0 版本已经删除了查询缓存功能
分析器
对SQL语句进行词法和语法的分析,并构造出语法树,方便预处理阶段检查字段和表是否存在
预处理器
*展开,检查字段和表是否存在
优化器
选择合适的索引,制定代价最小的查询计划
执行器
根据执行计划执行SQL语句,调用存储引擎接口,返回最终的结果给客户端
存储引擎层
存储引擎层主要负责对数据的存取
其架构是存入式的,意味着你可以根据具体的需要来选择存储引擎
创建的存储引擎有InnoDB和MyISAM等。
MySQL 5.5.5版本开始默认的是InoDB,如果想使用其他存储引擎可以通过engine = MyISAM类似这种形式来切换。
2.一条SQL语句在MySQL架构种的执行流程
首先需要通过连接器,建立客户端与服务器之间的连接,获得数据库的管理权限
如果查询缓存功能开启的话,会先去查询缓存,如果命中了,直接返回缓存种的结果给客户端。说一下给功能的优缺点,优点如果命中了查询效率会特别高,缺点,缓存失效太频繁,只要表一更新,查询缓存就会清空,8.0版本以取消该功能
如果没有命中,会通过分析器,对SQL语句进行词法语法的分析,并建立语法树
然后通过预处理器,把通配符展开,并检查字段和表是否存在
然后通过优化器,对SQL语句进行优化,选择合适的索引,指定查询代价最小的执行计划
然后通过执行器,判断对该表是否有执行权限,如果根据执行计划执行SQL语句,调用存储引擎接口,然会调用后的结果返回给客户端
在存储引擎种只要进行数据的存取工作,由于存储引擎的架构是插入时的,所以可以更改存储引擎。从5.5.5版本之后的存储引擎都是InnoDB,如果有特别需要,可以通过engine = MyISAM更改存储引擎
3.数据库中的三范式
第一范式(原子性)
原子性(数据库中存储的数据是不可再分的)
第二范式(唯一性)
唯一性(消除非主键部分依赖于联合主键中的一部分字段)
非主键外的其他字段必须完全依赖于主键,不能部分依赖于主键
比如现在有一个联合主键(a,b),有a才能有c,那么现在说明c依赖于a,但是c不依赖于b,所以c是部分依赖于主键的,不符合第三范式
比如这个例子,如果有主键的说应该是(学生,课程)的联合主键,但是明显其他字段对联合主键是部分依赖,所以不符合第三范式
解决方法
第三范式(独立性)
消除传递性依赖,比如B依赖于A,C也依赖于A,但C不能依赖于B。
解决方法,分表
总结
范式不是绝对要求的,有的时候为了满足需求还会特意违反范式。
4.char和varchar的区别
细说varchar与char有哪些区别?_char和varchar区别-CSDN博客
char和varchar都是用来存储字符串的
char(n):固定长度类型,存储的长度不足n时,自动补空间,查询的时候自动删空间
适用于固定长度的字符类型存储,比如密码
最大存储容量为255B
varchar(n):不定长类型
如果类的长度小于255用一个字节记录长度,大于用2个字节记录
最大存储容量为65535
5.varchar(100)和varchar(1000)的区别?
varchar(100) 会额外占用1个字节存储长度
varchar(1000)会额外占用2个字节存储长度
这样看到似乎存储长度设置的越大越好,反正占用的存储空间都是实际的字符大小。在磁盘上看是这样的,磁盘上分配的空间是按实际长度来分配的,但是内存上的空间是按设置的长度来分配的。但是在创建临时表或者排序的时候,是按内存中的长度排序的
6.谈一谈你对索引的理解?
索引就是为了快速查找数据的一种数据结构
可以提高查找效率,就好比目录和字典的关系,有了目录我们才能快速在字段点中查找文字
所以带来的负面影响
索引的创建和维护都需要消耗时间和物理空间。增删改查的时候索引也要动态维护,大大降低了维护的效率
索引的建立原则
在使用最频繁的,可以缩小查找范围、需要排序的字段上建立索引
不适合建立索引的情况
使用频率很少的列或者重复值很多的列不适合建立索引
对于一些特殊的数据类型,不宜创建索引,比如text因为太大了,索引的创建和维护是需要占用物理空间的
7.索引的底层使用的是什么数据结构
全文索引
使用倒排算法具体不清楚
哈希索引
基于哈希表实现的,查找非常迅速,但是不支持范围查找和排序。如果哈希冲突很多的话,索引的维护代价会比较高。哈希索引属于自适应类型的索引,不能认为创建。
B+树索引
B+树索引是按照顺序组织存储的,所以适合范围查找和排序。
B+树索引分为聚簇索引和非聚簇索引(二级索引要回表)
B+树的演变过程
最开始是二叉搜索树,它时按左下 上 右下 一次是小中大的这种形式递归存储的 但是如果数据按大小排序存储的话,会退化成一个链表
然后是平衡二叉树,但是平衡二叉树存储数据树的层数太高了,磁盘的IO次数太多,查询效率低
然后是B树,它是平衡多叉树,一个结点的子树可以有多个,树的高度大大降低了,磁盘IO次数减少,查询效率边高了
最后是B+树,他是一种特殊的平衡多叉树,非叶子结点存索引,叶子阶段存索引和数据。对于非叶子结点而言,存储索引显而易见更节省空间,所以树的层数会特别的少,磁盘IO次数也很少,查询效率高。并且B+树的叶子结点意见用双向链表连接了,支持范围查找和排序
8.谈谈你对B+树的了解
可以说以下B+树的演变过程
然后说以下B+树如果查找的
B+树进行查找操作时,会在根节点进行二分搜查找,找到一个key所在的指针,然后递归的进行二分查找,直到找到了叶子结点,然后在叶子结点上二分查找,直到找出key所对应data
缺点
B+树输入删除的适合会破坏平衡性,因此在插入删除操作之后需要对树进行一个分类、合并、旋转等操作来维护平衡性,维护代价较高
索引会被多次存储
9.为什么InnoDB存储引擎选择B+树而不是B树?
B+树减少了IO次数
只有叶子存放数据,其他非叶子结点存放索引。相比于B树,这种存储模式会使树的高度减少非常多,即使是上千万的数据只需要三四层高度就可以满足,查询一个数据仅需要3到4次磁盘I/O。
B+树的查询稳定性会更高
由于数据都在叶子结点上,所以B+树只有遍历到最底层才能找到数据,查找效率稳定在O(nlogn)
B+树更加适合范围查找
B+树的叶子结点用双向链表连接在一起,更加适合于范围查找,而B树需要通过中序遍历来扫描,B+树范围查找的效率更高
10.谈谈你对聚簇索引的理解?
什么是聚簇索引?
聚簇索引是非叶子结点放索引,叶子节点放索引和一行完整数据的B+树数据结构。它把索引和数据聚到了一起
什么字段适合创建聚簇索引?
在InnoDB中,一般设置主键为聚簇索引,如果没有主键的话,InnoDB会选择一个非空且唯一的字段创建,如果还没有,会隐式定义一个主键作为聚簇索引。这段话也就表明了,一个表一定会有一个聚簇索引,把索引和完整数据聚合到一起的B+树结构
优点
索引和数据放在了一起,数据访问更加迅速
缺点
插入速度严重依赖于插入顺序
因为一般主键为聚簇索引,一般设置自增的主键就是因为这个原因
更新聚簇索引列的代价很高
所以选择与业务无关的列作为主键
可能会面临页分裂
B+树会把一个叶子结点优化成一个磁盘块,突然插入一条数据可能磁盘块放不下了,自增
聚簇索引和非聚簇索引的区别
聚簇索引叶子结点存的data是完整的数据而非聚簇结点data存的是主键,非聚簇索引可能会面临回表的情况,比如一个age的非聚簇索引,我要查age和那么,会先用非聚簇索引找到age然后看data里面的主键,按这个主键回表到聚簇索引中查找name。非聚簇索引不回标就完成一此查询的现象成为索引覆盖
11.谈谈你对哈希索引的理解
哈希索引是基于哈希表的一种索引结构,如果命中的话,可以在O(1)时间进行查找,但是由于其无序性,无法进行范围查找和排序。
InnoDB存储引擎有一个特殊的功能叫自适应哈希索引,当一个索引值被频繁查找的时候,会在B+上索引上再建立一个哈希索引,这样就让B+树索引具有了哈希索引的一些特点,比如快速哈希查找
12.谈谈你对覆盖索引的认识
覆盖索引是非聚簇索引不用回表就完成查询的现象,具体来说比如你建立了一个age的非聚簇索引,你要根据age去查找age和主键,这时候就不需要回标就可以完成本次查询。
13.索引的分类?
按数据结构分
全文索引
哈希索引
B+树索引
按物理存储角度
聚簇索引
非举措索引
按逻辑角度
普通索引
唯一索引
主键索引
联合索引
全文索引
14.谈谈你对最左前缀原则的理解?、
当使用联合索引的时候,需要满足最左前缀原则。
(name,age)的联合索引-->创建了(name)、(age)的索引
(name、age、sex)的联合索引-->创建了(name)、(name,age)、(name、age、sex)的索引
最左前缀原则会一直向右匹配知道遇到范围查找(> < between like)就会停止匹配
c++
索引下推
现在我们知道,对于联合索引(a, b),在执行 select * from table where a > 1 and b = 2 语句的时候,只有 a 字段能用到索引,那在联合索引的 B+Tree 找到第一个满足条件的主键值(ID 为 2)后,还需要判断其他条件是否满足(看 b 是否等于 2),那是在联合索引里判断?还是回主键索引去判断呢?
在 MySQL 5.6 之前,只能从 ID2 (主键值)开始一个个回表,到「主键索引」上找出数据行,再对比 b 字段值。
而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
当你的查询语句的执行计划里,出现了 Extra 为 Using index condition,那么说明使用了索引下推的优化。
在(a,b,c,d)的联合索引中,where a = 1 and b = 2 and c > 3 and d = 4
会用到a b c 的索引,d是用不到索引的
当不考虑排序和分组时,将选择性最高(数据出现的频率少,更容易过滤数据)的列放在前面。
15.怎么知道创建的索引有没有被使用过?或者说怎么才可以知道这条语句运行的很慢的原因?
explain+查询的这条语句,一条MySQL语句经历分析器、优化器、执行器,其中尽力优化器的时候会拿到这条语句的分析。
16.索引失效的情况
sql
create index ename_idex on emp(ename);
create index sal_idex on emp(sal);
#All全文查找
explain select * from emp;
#ename_idex
explain select ename from emp;
#sal_index
explain select empno from emp;
#ename_index
explain select empno from where ename = 'smith';
#primary key index
explain select ename from emp where empno = 7396;
#ALL 索引失效 or 有一边没用到索引
explain select * from emp where job = 'clerk' or ename = 'clerk';
#ALL 索引失效 or 有一边没用到索引
explain select empno from emp where empno = 7396 or job = 'clerk';
#empno_index、sal_index
explain select * from emp where empno = 7396 or sal > 5000;
#索引使用不等于相当于全文查找了,用索引没有意义
explain select * from emp where sal != 5000;
#索引使用不等于相当于全文查找了,用索引没有意义
explain select * from emp where sal > 5000 or sal <5000;
#like模糊查询,不查开头,查其他情况会导致所以索引失效
explain select * from emp where ename like '%s%';
#索引参与计算,会导致索引失效
explain select * from emp where sal + 1 > 5000;
查询条件包含or,or的前后不都是索引
模糊查询like,'%s%' '%s'这种情况
索引列实现!=这种情况
对索引使用函数
索引参与计算
联合索引没有遵循最左匹配原则
全表扫描比索引快
17.查询性能的优化方法有哪些?
减少请求的数据量
减少返回的必要列:不要使用select *
减少返回的必要行:使用limit限制返回的行数
减少服务器扫描的行数
给经常使用的列建立索引,以减少服务器扫描的行数
18.InnoDB和MyISAM的区别?
事务方面
InnoDB支持事务,MyISAM不支持事务
(事务:一组原子性的SQL查询,事务要么全部成功,要么全部执行失败,如果失败了前面执行成功的也要回滚,DML语句的执行代表事务的开始,事务的结束要么是提交事务即全部执行成功,要么是回滚执行失败)
全文索引方面
InoDB在5.6之后支持全文索引,MyISAM支持全文索引
关于count()
对于count函数,MyISAM保存了表的具体行数,可以直接返回,而InnoDB没有,需要扫描每一行然后返回行数。
外键方面
InnoDB支持外键,MyISAM不支持外键
student score
constraint fk1 foreign key (student_id) references stduent(id);
锁方面
InnoDB支持表锁和行锁,MyISAM只支持表锁
19.谈谈你对水平切分和垂直切分的理解
水平切分
水平切割就是将一个表中的记录水平切分成多个结构相同的表
当一个表中的数据不断增多的时候,水平切割时必然的,它可以减缓单个数据库的压力
垂直切分
垂直切割就时将一个表中的列切分成多个表,通常时按照列于列之间的紧密程度进行切割的,将尝试用的放在一个表,不常使用的放在一个表中
(*)20.主从复制中涉及到哪三个线程?
binlog线程
主要负责将主服务器上数据的更改写到binary log(二进制日志)文件中
I/O线程
读取BinLog日志文件中的的内容,并写入从服务器RelayLog日志文件中
SQL线程
负责读取RelayLog日志文件中的内容,并重放其中的SQL语句
(*)21.主从同步的延迟原因及解决方法?
(*)22.谈谈你对数据库读写分离的理解?
主服务器用来读,从服务器用来写,主从服务器负责格子的读写,极大程度缓解了锁的争用
23.请你描述下事务的特性?
ACID
A(atomicity):原子性
事务时最小工作单元,不可再分,事务中的SQL语句要么全部执行成功,要么全部失败回滚。
就好比你在超市中买东西,你拿了一些商品去付款。要么付款成功你把东西拿走,钱给老板。要么付款失败,你的东西要还给老板,也无需付款,就像你刚开始来超市一样
C(consistency):一致性
数据库总时由一个状态到另外一个状态,不会由于某条语句的失败而出现其他状态
就比如你有400元,你的朋友有600元,你想给你朋友转账。最后的结果一定是你200,朋友800。不能出现你200,你朋友600这种中间状态
I(isolation):隔离性
通常来说,一个事务在没提交之前,对其他事务时不可见的
D(durability):持久性
事务一旦提交,其做的修改会持久的保存到数据库中。
24.谈谈你对事务隔离级别的理解?
未提交读(READ_UNCOMMITTED)
最低的隔离级别,一个事务没提交就可以被其他事务读到
可能会导致脏读、不可重复读、幻读等问题
提交读(READ_COMMITTED)
可以解读脏读问题,但是仍会产生不可重复度和幻读问题
可重复读(REPEATABLEE_READ)
在一个事务中,对一个字段多次读取的结果都是一样的。可以解决脏读和不可重复读问题,但是无法彻底解决幻读问题
串行化(SERIALIZABLE)
一个事务执行完之后另外一个事务才能执行,完全服从ACID隔离级别,可以解决脏读、不可重复度、幻读问题
25.解释以下什么时脏读、幻读、不可重复读?
脏读
表示一个事务还没有提交,就被另外一个事务读到了。由于未提交的事务可能会回滚,另外一个事务读到的数据就是脏数据
不可重复读
在一个事务中,俩次读取到的结果不一样,因为另外一个事务提交修改了要读取的数据。
不可重复读重点是在修改,同样的条件,多次读取结果不同
幻读
幻读重点在于新增和删除:同样的条件,第一次和第二次读出来的记录数不一样
26.MySQL默认的隔离级别是什么?
MySQL默认隔离级别是可重复读(REPEATABLE_READ)
Oracle默认READ_COMMITTED
(*)27.谈谈你对MVCC的了解?
Multi-Version Concurrency Control(MVCC):多版本并发控制
数据库中常见的并发场景
1.读-读:不存在任何问题,也不需要并发控制
2.读-写:存在线程安全问题,可能会造成事务的隔离级别,可能会遇到脏读、幻读、不可重复读
3.写-写:有线程安全问题,可能会造成数据更新丢失问题
MVCC是为了解决幻读问题
再MySQL默认的存储引擎InnDB中,默认的事务隔离级别是可重复度,但是仍然后造成幻读问题(为啥啊),该问题MySQL采用了俩种解决方法
1.快照读(普通的select语句):是通过MVCC方式解决幻读问题的,因为再可重复读隔离级别下,事务执行过程中所看到的数据都是事务启动时的数据,即使中途其他是我对数据进行了修改,是查不出该事务的。因为读取的都是其实启动时的数据,所以这就很好避免了幻读问题
2.当前读(select ... for update 等语句),是通过next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。
(*)28.说以下MySQL的行锁和表锁?
MyISAM支持表锁,InoDB支持表锁和行锁,默认是行锁
表级锁:开销小,加锁快,不会出现死锁。颗粒度大,发生锁冲突的概率最高,并发量最低
行级锁:开销大,加锁慢,会出现死锁。颗粒度小,发生锁冲突的概率小,并发量高
(*)29.InnoDB存储引擎的锁的算法有哪些?
1.Record lock:单个行记录上的锁
2.Gap lock:间隙锁,锁定一个范围,不包括记录本身
3.Next-key lock:record+gap 锁定一个范围,包含记录本身
(*)30.MySQL问题排查都有哪些手段?
1.使用show processlist 命令查看当前所有连接信息
2.使用explain命令查询SQL语句的执行计划
3.开启慢查询日志,查看慢查询的SQL
(*)31.MySQL数据库CPU飙升到500%的话它怎么处理?
(*)32.MySQL的redo log,undo log , bin log 都是干什么的
33.什么是反之和反范式,以及各自的优缺点?
范式
构建数据库需要一定的规则,这中规则或者说是规范就是范式,在MySQL关系型数据库中有三范式,分别是原子性、唯一性和独立性
优点:有了范式可以减少数据的冗余,数据表更新操作快、占用的内容少
缺点:为了满足三范式会进行分表,查询时通常需要连表查,更难进行索引优化
反范式
反范式就是通过冗余数据来提高查询性能
优点:数据都在一个表中,可以减少表关联,更好进行索引优化
缺点:存在大量的冗余数据,数据的维护成本更高
34.limit 1000000,10加载很慢,怎么解决?
如果id是连续的,可以直接 where id >1000000 limit 10
mysqlselect id, name from emp where id > 1000000 limit 10;
如果id不连接,使用子查询计算id
mysqlselect id, name from emp where id ( select id from limit 1000000, 1 )limit 10;
如果id是索引的话,可以先order by对id排序在limit
mysqlselect id, name from emp order by limit 1000000, 10;
业务上应该避免这么大的分页数
35.drop、truncate、delete的区别
drop
删除整张表,包括数据和结构,属于DDL,不能回滚
truncate
删除表中的所有数据,保留了结构,属于DDL,不能回滚
delete
删除表中的部分数据或者全部数据,逐行删除,速度慢,属于DML,可以回滚
速度方面
drop > truncate > delete
36.union 与 union all的区别
union
union是将俩个结果集进行合并,会去重,同时进行默认规则的排序
union all
union all也是将俩个结果集进行合并,不会去重,包括重复行,不进行排序
union的效率高于union all
37.MySQL的内连接、左外连接、右外连接有什么区别?
内连接
内连接是在俩个表连表查询的时候,只保留完全匹配的结果集
左外连接
连表查询的时候,不但保留完全匹配的结果集还有左表中的所有行
右外连接
连表查询的时候,不但保留完全匹配的结果集还有右表中的所有行
38.常见的聚合函数右哪些?使用聚合函数需要注意什么
avg
sum
count
max
min
注意
聚合函数自动忽略空值
聚合函数在where之后使用,因为where遍历表的时候聚合函数还有算出来结果那
39.一条SQL查询语句的执行顺序
40.索引的优缺点
优点
减少服务器需要扫描的数据量
帮助服务器进行排序和临时表
可以将随机IO编程顺序IO,提高查找性能
缺点
空间角度,创建索引占用物理空间
时间角度,所以的维护代价很高,需要花费时间
41.索引的设计原则
选择经常作为查询条件的列作为索引
为经常需要排序和分组和联合操作的列创建索引
创建唯一性索引
限制索引的数量
小表不建议建立索引
尽量使用前缀索引
删除不再使用或者很少使用的索引
42.索引的使用原则
独立的列
使用前缀索引
使用联合索引
联合索引,把选择性高的列放在前面
合适的主键
不建立重复或者不适用的索引
43.如何判断SQL是否走了索引?
在sql语句前面加explain关键字
44.说一下联合索引
定义
将多个列组合成一个索引,该索引就被成为联合索引
在InnoDB的存储引擎下,默认的索引结构是B+树结构,也就是说非叶子结点存储的是联合索引,叶子节点,存储的是联合索引和主键
满足最左前缀原则
因为联合索引在创建B+树索引的时候,顺序是先按第一个字段排序,如果第一个字段相同再按第二个字段排序。这也就导致了其他字段的顺序依赖于最左边的第一个字段
所以说如果你的where查询条件不是从最左边开始的,就无法使用索引
例如:创建了(a,b,c)的联合索引,你的where 条件 是b c怎么怎么样就无法用到bc索引,因为bc再B+树种是没有顺序的,它依赖于a的顺序
还有就是范围查找后面的字段会索引失效
比如 (a,b,c) where a=1 and b>2 and c = 3;
这种情况就无法使用到了c索引,因为范围查找实际上是按照链表进行遍历,等遍历到b>2的时候,c以及无序了
索引下推
索引下推是在5.6版本以后引入的,目的是在联合索引遍历的过程中,如果第一个字段相同,那么不用回表找第二个字段,直接在联合索引的B+树种就能判断是否满足条件。
索引选择性高的放左边提升查找效率
另外,建立联合索引时的字段顺序,对索引效率也有很大影响。越靠前的字段被用于索引过滤的概率越高,实际开发工作中建立联合索引时,要把区分度大的字段排在前面,这样区分度大的字段越有可能被更多的 SQL 使用到。
区分度就是某个字段 column 不同值的个数「除以」表的总行数,计算公式如下:
比如,性别的区分度就很小,不适合建立索引或不适合排在联合索引列的靠前的位置,而 UUID 这类字段就比较适合做索引或排在联合索引列的靠前的位置。
因为如果索引的区分度很小,假设字段的值分布均匀,那么无论搜索哪个值都可能得到一半的数据。在这些情况下,还不如不要索引,因为 MySQL 还有一个查询优化器,查询优化器发现某个值出现在表的数据行中的百分比(惯用的百分比界线是"30%")很高的时候,它一般会忽略索引,进行全表扫描。
45.索引的优缺点
优点
可以加快查找的效率,使数据有序存储
缺点
索引的创建的需要物理空间的,如果索引特别大的话,那么会占用很大的物理空间
索引的创建和维护都需要时间
增删改会降低表的查找效率,因为这些操作很可能破坏索引的有序性,为了重新实现有序性需要花费时间去维护索引
所以索引不是万能钥匙,是根据场景来使用的
46.什么需要/不需要创建索引?
什么时候需要?
字段又唯一性限制
经常在where条件之后出现的字段,如果有多个字段的话从创建联合索引
经常用于group by或者order by的字段,这样查询的时候就不需要去做一次排序了,因为索引本身就是有序的
什么时候不需要?
字段中存在着大量的重复数据,比如性别不是男就是女,这样的字段选择性太低,无法快速缩小查找范围
表中的数据量很少,不需要创建索引
经常跟新的字段不用创建索引,因为索引的维护代价很大
47.索引优化的方法有哪些?
使用前缀索引优化
对于长度很长的字段如果非要创建索引的话,最好创建前缀索引,就是选该字段的一部分作为索引,但是要保证该部分具有高选择性
使用覆盖索引优化
覆盖索引二级索引查询查询数据的时候,不用回表就查询到想要的数据的一种现场。
主键索引最好是自增的
顺序插入可以减少索引的维护代价,而且可以预防页分裂的现象
索引最好设置为非空
防止索引失效
1.or的左右两边不都是索引
2.where后面的条件是!=这种
3.like '%s' '%s%'
假设你建立了name字段的索引,那么name字段作为索引在B+树上的顺序是有序的,但是如果你不是从第一个字母去比较的话,索引就会失效,因为它变得无序了
4.索引列参与计算了
5.索引列放在函数里面了
6.使用联合索引的时候,没有遵循最左前缀原则
48.count(1)、count(*)、count(主键)、count(其他字段)
count(1)=count(*)>count(主键)>count(其他字段)
49.InnoDB存储引擎通过什么技术来保证ACID这四个特定
原子性是通过undo log(回滚日志)来实现的
一致性是通过持久性+原子性+隔离性
隔离性是通过MVCC(多版本并发控制)或者锁来实现的
持久性是通过redo log(重做日志)来实现的# 参考大庆指针面试宝典和xiaolincoding.com
优质文章
MySQL 可重复读隔离级别,完全解决幻读了吗? | 小林coding (xiaolincoding.com)
1.请说一下对MySQL架构的了解?
架构图
预处理阶段的语法树的结构
具体而言MySQL架构可以分为Server层和存储引擎层俩部分
Server层
连接器
用于建立客户端于服务器之间的连接,相当于客户端获取到了数据库的管理权限
查询缓存
一个SQL语句首先会到缓存中查看这条语句之前是否被查询过(如果开启了查询缓存功能),如果查询过直接返回缓存中的结果给客户端。
该机制的优点是如果命中的话,效率很高。缺点是缓存失效的频率太高,只要表一进行更新,该表的所以查询缓存都会被清空,因为该缺点,MySQL 8.0 版本已经删除了查询缓存功能
分析器
对SQL语句进行词法和语法的分析,并构造出语法树,方便预处理阶段检查字段和表是否存在
预处理器
*展开,检查字段和表是否存在
优化器
选择合适的索引,制定代价最小的查询计划
执行器
根据执行计划执行SQL语句,调用存储引擎接口,返回最终的结果给客户端
存储引擎层
存储引擎层主要负责对数据的存取
其架构是存入式的,意味着你可以根据具体的需要来选择存储引擎
创建的存储引擎有InnoDB和MyISAM等。
MySQL 5.5.5版本开始默认的是InoDB,如果想使用其他存储引擎可以通过engine = MyISAM类似这种形式来切换。
2.一条SQL语句在MySQL架构种的执行流程
首先需要通过连接器,建立客户端与服务器之间的连接,获得数据库的管理权限
如果查询缓存功能开启的话,会先去查询缓存,如果命中了,直接返回缓存种的结果给客户端。说一下给功能的优缺点,优点如果命中了查询效率会特别高,缺点,缓存失效太频繁,只要表一更新,查询缓存就会清空,8.0版本以取消该功能
如果没有命中,会通过分析器,对SQL语句进行词法语法的分析,并建立语法树
然后通过预处理器,把通配符展开,并检查字段和表是否存在
然后通过优化器,对SQL语句进行优化,选择合适的索引,指定查询代价最小的执行计划
然后通过执行器,判断对该表是否有执行权限,如果根据执行计划执行SQL语句,调用存储引擎接口,然会调用后的结果返回给客户端
在存储引擎种只要进行数据的存取工作,由于存储引擎的架构是插入时的,所以可以更改存储引擎。从5.5.5版本之后的存储引擎都是InnoDB,如果有特别需要,可以通过engine = MyISAM更改存储引擎
3.数据库中的三范式
第一范式(原子性)
原子性(数据库中存储的数据是不可再分的)
第二范式(唯一性)
唯一性(消除非主键部分依赖于联合主键中的一部分字段)
非主键外的其他字段必须完全依赖于主键,不能部分依赖于主键
比如现在有一个联合主键(a,b),有a才能有c,那么现在说明c依赖于a,但是c不依赖于b,所以c是部分依赖于主键的,不符合第三范式
比如这个例子,如果有主键的说应该是(学生,课程)的联合主键,但是明显其他字段对联合主键是部分依赖,所以不符合第三范式
解决方法
第三范式(独立性)
消除传递性依赖,比如B依赖于A,C也依赖于A,但C不能依赖于B。
解决方法,分表
总结
范式不是绝对要求的,有的时候为了满足需求还会特意违反范式。
4.char和varchar的区别
细说varchar与char有哪些区别?_char和varchar区别-CSDN博客
char和varchar都是用来存储字符串的
char(n):固定长度类型,存储的长度不足n时,自动补空间,查询的时候自动删空间
适用于固定长度的字符类型存储,比如密码
最大存储容量为255B
varchar(n):不定长类型
如果类的长度小于255用一个字节记录长度,大于用2个字节记录
最大存储容量为65535
5.varchar(100)和varchar(1000)的区别?
varchar(100) 会额外占用1个字节存储长度
varchar(1000)会额外占用2个字节存储长度
这样看到似乎存储长度设置的越大越好,反正占用的存储空间都是实际的字符大小。在磁盘上看是这样的,磁盘上分配的空间是按实际长度来分配的,但是内存上的空间是按设置的长度来分配的。但是在创建临时表或者排序的时候,是按内存中的长度排序的
6.谈一谈你对索引的理解?
索引就是为了快速查找数据的一种数据结构
可以提高查找效率,就好比目录和字典的关系,有了目录我们才能快速在字段点中查找文字
所以带来的负面影响
索引的创建和维护都需要消耗时间和物理空间。增删改查的时候索引也要动态维护,大大降低了维护的效率
索引的建立原则
在使用最频繁的,可以缩小查找范围、需要排序的字段上建立索引
不适合建立索引的情况
使用频率很少的列或者重复值很多的列不适合建立索引
对于一些特殊的数据类型,不宜创建索引,比如text因为太大了,索引的创建和维护是需要占用物理空间的
7.索引的底层使用的是什么数据结构
全文索引
使用倒排算法具体不清楚
哈希索引
基于哈希表实现的,查找非常迅速,但是不支持范围查找和排序。如果哈希冲突很多的话,索引的维护代价会比较高。哈希索引属于自适应类型的索引,不能认为创建。
B+树索引
B+树索引是按照顺序组织存储的,所以适合范围查找和排序。
B+树索引分为聚簇索引和非聚簇索引(二级索引要回表)
B+树的演变过程
最开始是二叉搜索树,它时按左下 上 右下 一次是小中大的这种形式递归存储的 但是如果数据按大小排序存储的话,会退化成一个链表
然后是平衡二叉树,但是平衡二叉树存储数据树的层数太高了,磁盘的IO次数太多,查询效率低
然后是B树,它是平衡多叉树,一个结点的子树可以有多个,树的高度大大降低了,磁盘IO次数减少,查询效率边高了
最后是B+树,他是一种特殊的平衡多叉树,非叶子结点存索引,叶子阶段存索引和数据。对于非叶子结点而言,存储索引显而易见更节省空间,所以树的层数会特别的少,磁盘IO次数也很少,查询效率高。并且B+树的叶子结点意见用双向链表连接了,支持范围查找和排序
8.谈谈你对B+树的了解
可以说以下B+树的演变过程
然后说以下B+树如果查找的
B+树进行查找操作时,会在根节点进行二分搜查找,找到一个key所在的指针,然后递归的进行二分查找,直到找到了叶子结点,然后在叶子结点上二分查找,直到找出key所对应data
缺点
B+树输入删除的适合会破坏平衡性,因此在插入删除操作之后需要对树进行一个分类、合并、旋转等操作来维护平衡性,维护代价较高
索引会被多次存储
9.为什么InnoDB存储引擎选择B+树而不是B树?
B+树减少了IO次数
只有叶子存放数据,其他非叶子结点存放索引。相比于B树,这种存储模式会使树的高度减少非常多,即使是上千万的数据只需要三四层高度就可以满足,查询一个数据仅需要3到4次磁盘I/O。
B+树的查询稳定性会更高
由于数据都在叶子结点上,所以B+树只有遍历到最底层才能找到数据,查找效率稳定在O(nlogn)
B+树更加适合范围查找
B+树的叶子结点用双向链表连接在一起,更加适合于范围查找,而B树需要通过中序遍历来扫描,B+树范围查找的效率更高
10.谈谈你对聚簇索引的理解?
什么是聚簇索引?
聚簇索引是非叶子结点放索引,叶子节点放索引和一行完整数据的B+树数据结构。它把索引和数据聚到了一起
什么字段适合创建聚簇索引?
在InnoDB中,一般设置主键为聚簇索引,如果没有主键的话,InnoDB会选择一个非空且唯一的字段创建,如果还没有,会隐式定义一个主键作为聚簇索引。这段话也就表明了,一个表一定会有一个聚簇索引,把索引和完整数据聚合到一起的B+树结构
优点
索引和数据放在了一起,数据访问更加迅速
缺点
插入速度严重依赖于插入顺序
因为一般主键为聚簇索引,一般设置自增的主键就是因为这个原因
更新聚簇索引列的代价很高
所以选择与业务无关的列作为主键
可能会面临页分裂
B+树会把一个叶子结点优化成一个磁盘块,突然插入一条数据可能磁盘块放不下了,自增
聚簇索引和非聚簇索引的区别
聚簇索引叶子结点存的data是完整的数据而非聚簇结点data存的是主键,非聚簇索引可能会面临回表的情况,比如一个age的非聚簇索引,我要查age和那么,会先用非聚簇索引找到age然后看data里面的主键,按这个主键回表到聚簇索引中查找name。非聚簇索引不回标就完成一此查询的现象成为索引覆盖
11.谈谈你对哈希索引的理解
哈希索引是基于哈希表的一种索引结构,如果命中的话,可以在O(1)时间进行查找,但是由于其无序性,无法进行范围查找和排序。
InnoDB存储引擎有一个特殊的功能叫自适应哈希索引,当一个索引值被频繁查找的时候,会在B+上索引上再建立一个哈希索引,这样就让B+树索引具有了哈希索引的一些特点,比如快速哈希查找
12.谈谈你对覆盖索引的认识
覆盖索引是非聚簇索引不用回表就完成查询的现象,具体来说比如你建立了一个age的非聚簇索引,你要根据age去查找age和主键,这时候就不需要回标就可以完成本次查询。
13.索引的分类?
按数据结构分
全文索引
哈希索引
B+树索引
按物理存储角度
聚簇索引
非举措索引
按逻辑角度
普通索引
唯一索引
主键索引
联合索引
全文索引
14.谈谈你对最左前缀原则的理解?、
当使用联合索引的时候,需要满足最左前缀原则。
(name,age)的联合索引-->创建了(name)、(age)的索引
(name、age、sex)的联合索引-->创建了(name)、(name,age)、(name、age、sex)的索引
最左前缀原则会一直向右匹配知道遇到范围查找(> < between like)就会停止匹配
c++
索引下推
现在我们知道,对于联合索引(a, b),在执行 select * from table where a > 1 and b = 2 语句的时候,只有 a 字段能用到索引,那在联合索引的 B+Tree 找到第一个满足条件的主键值(ID 为 2)后,还需要判断其他条件是否满足(看 b 是否等于 2),那是在联合索引里判断?还是回主键索引去判断呢?
在 MySQL 5.6 之前,只能从 ID2 (主键值)开始一个个回表,到「主键索引」上找出数据行,再对比 b 字段值。
而 MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
当你的查询语句的执行计划里,出现了 Extra 为 Using index condition,那么说明使用了索引下推的优化。
在(a,b,c,d)的联合索引中,where a = 1 and b = 2 and c > 3 and d = 4
会用到a b c 的索引,d是用不到索引的
当不考虑排序和分组时,将选择性最高(数据出现的频率少,更容易过滤数据)的列放在前面。
15.怎么知道创建的索引有没有被使用过?或者说怎么才可以知道这条语句运行的很慢的原因?
explain+查询的这条语句,一条MySQL语句经历分析器、优化器、执行器,其中尽力优化器的时候会拿到这条语句的分析。
16.索引失效的情况
sql
create index ename_idex on emp(ename);
create index sal_idex on emp(sal);
#All全文查找
explain select * from emp;
#ename_idex
explain select ename from emp;
#sal_index
explain select empno from emp;
#ename_index
explain select empno from where ename = 'smith';
#primary key index
explain select ename from emp where empno = 7396;
#ALL 索引失效 or 有一边没用到索引
explain select * from emp where job = 'clerk' or ename = 'clerk';
#ALL 索引失效 or 有一边没用到索引
explain select empno from emp where empno = 7396 or job = 'clerk';
#empno_index、sal_index
explain select * from emp where empno = 7396 or sal > 5000;
#索引使用不等于相当于全文查找了,用索引没有意义
explain select * from emp where sal != 5000;
#索引使用不等于相当于全文查找了,用索引没有意义
explain select * from emp where sal > 5000 or sal <5000;
#like模糊查询,不查开头,查其他情况会导致所以索引失效
explain select * from emp where ename like '%s%';
#索引参与计算,会导致索引失效
explain select * from emp where sal + 1 > 5000;
查询条件包含or,or的前后不都是索引
模糊查询like,'%s%' '%s'这种情况
索引列实现!=这种情况
对索引使用函数
索引参与计算
联合索引没有遵循最左匹配原则
全表扫描比索引快
17.查询性能的优化方法有哪些?
减少请求的数据量
减少返回的必要列:不要使用select *
减少返回的必要行:使用limit限制返回的行数
减少服务器扫描的行数
给经常使用的列建立索引,以减少服务器扫描的行数
18.InnoDB和MyISAM的区别?
事务方面
InnoDB支持事务,MyISAM不支持事务
(事务:一组原子性的SQL查询,事务要么全部成功,要么全部执行失败,如果失败了前面执行成功的也要回滚,DML语句的执行代表事务的开始,事务的结束要么是提交事务即全部执行成功,要么是回滚执行失败)
全文索引方面
InoDB在5.6之后支持全文索引,MyISAM支持全文索引
关于count()
对于count函数,MyISAM保存了表的具体行数,可以直接返回,而InnoDB没有,需要扫描每一行然后返回行数。
外键方面
InnoDB支持外键,MyISAM不支持外键
student score
constraint fk1 foreign key (student_id) references stduent(id);
锁方面
InnoDB支持表锁和行锁,MyISAM只支持表锁
19.谈谈你对水平切分和垂直切分的理解
水平切分
水平切割就是将一个表中的记录水平切分成多个结构相同的表
当一个表中的数据不断增多的时候,水平切割时必然的,它可以减缓单个数据库的压力
垂直切分
垂直切割就时将一个表中的列切分成多个表,通常时按照列于列之间的紧密程度进行切割的,将尝试用的放在一个表,不常使用的放在一个表中
(*)20.主从复制中涉及到哪三个线程?
binlog线程
主要负责将主服务器上数据的更改写到binary log(二进制日志)文件中
I/O线程
读取BinLog日志文件中的的内容,并写入从服务器RelayLog日志文件中
SQL线程
负责读取RelayLog日志文件中的内容,并重放其中的SQL语句
(*)21.主从同步的延迟原因及解决方法?
(*)22.谈谈你对数据库读写分离的理解?
主服务器用来读,从服务器用来写,主从服务器负责格子的读写,极大程度缓解了锁的争用
23.请你描述下事务的特性?
ACID
A(atomicity):原子性
事务时最小工作单元,不可再分,事务中的SQL语句要么全部执行成功,要么全部失败回滚。
就好比你在超市中买东西,你拿了一些商品去付款。要么付款成功你把东西拿走,钱给老板。要么付款失败,你的东西要还给老板,也无需付款,就像你刚开始来超市一样
C(consistency):一致性
数据库总时由一个状态到另外一个状态,不会由于某条语句的失败而出现其他状态
就比如你有400元,你的朋友有600元,你想给你朋友转账。最后的结果一定是你200,朋友800。不能出现你200,你朋友600这种中间状态
I(isolation):隔离性
通常来说,一个事务在没提交之前,对其他事务时不可见的
D(durability):持久性
事务一旦提交,其做的修改会持久的保存到数据库中。
24.谈谈你对事务隔离级别的理解?
未提交读(READ_UNCOMMITTED)
最低的隔离级别,一个事务没提交就可以被其他事务读到
可能会导致脏读、不可重复读、幻读等问题
提交读(READ_COMMITTED)
可以解读脏读问题,但是仍会产生不可重复度和幻读问题
可重复读(REPEATABLEE_READ)
在一个事务中,对一个字段多次读取的结果都是一样的。可以解决脏读和不可重复读问题,但是无法彻底解决幻读问题
串行化(SERIALIZABLE)
一个事务执行完之后另外一个事务才能执行,完全服从ACID隔离级别,可以解决脏读、不可重复度、幻读问题
25.解释以下什么时脏读、幻读、不可重复读?
脏读
表示一个事务还没有提交,就被另外一个事务读到了。由于未提交的事务可能会回滚,另外一个事务读到的数据就是脏数据
不可重复读
在一个事务中,俩次读取到的结果不一样,因为另外一个事务提交修改了要读取的数据。
不可重复读重点是在修改,同样的条件,多次读取结果不同
幻读
幻读重点在于新增和删除:同样的条件,第一次和第二次读出来的记录数不一样
26.MySQL默认的隔离级别是什么?
MySQL默认隔离级别是可重复读(REPEATABLE_READ)
Oracle默认READ_COMMITTED
(*)27.谈谈你对MVCC的了解?
Multi-Version Concurrency Control(MVCC):多版本并发控制
数据库中常见的并发场景
1.读-读:不存在任何问题,也不需要并发控制
2.读-写:存在线程安全问题,可能会造成事务的隔离级别,可能会遇到脏读、幻读、不可重复读
3.写-写:有线程安全问题,可能会造成数据更新丢失问题
MVCC是为了解决幻读问题
再MySQL默认的存储引擎InnDB中,默认的事务隔离级别是可重复度,但是仍然后造成幻读问题(为啥啊),该问题MySQL采用了俩种解决方法
1.快照读(普通的select语句):是通过MVCC方式解决幻读问题的,因为再可重复读隔离级别下,事务执行过程中所看到的数据都是事务启动时的数据,即使中途其他是我对数据进行了修改,是查不出该事务的。因为读取的都是其实启动时的数据,所以这就很好避免了幻读问题
2.当前读(select ... for update 等语句),是通过next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。
(*)28.说以下MySQL的行锁和表锁?
MyISAM支持表锁,InoDB支持表锁和行锁,默认是行锁
表级锁:开销小,加锁快,不会出现死锁。颗粒度大,发生锁冲突的概率最高,并发量最低
行级锁:开销大,加锁慢,会出现死锁。颗粒度小,发生锁冲突的概率小,并发量高
(*)29.InnoDB存储引擎的锁的算法有哪些?
1.Record lock:单个行记录上的锁
2.Gap lock:间隙锁,锁定一个范围,不包括记录本身
3.Next-key lock:record+gap 锁定一个范围,包含记录本身
(*)30.MySQL问题排查都有哪些手段?
1.使用show processlist 命令查看当前所有连接信息
2.使用explain命令查询SQL语句的执行计划
3.开启慢查询日志,查看慢查询的SQL
(*)31.MySQL数据库CPU飙升到500%的话它怎么处理?
(*)32.MySQL的redo log,undo log , bin log 都是干什么的
33.什么是反之和反范式,以及各自的优缺点?
范式
构建数据库需要一定的规则,这中规则或者说是规范就是范式,在MySQL关系型数据库中有三范式,分别是原子性、唯一性和独立性
优点:有了范式可以减少数据的冗余,数据表更新操作快、占用的内容少
缺点:为了满足三范式会进行分表,查询时通常需要连表查,更难进行索引优化
反范式
反范式就是通过冗余数据来提高查询性能
优点:数据都在一个表中,可以减少表关联,更好进行索引优化
缺点:存在大量的冗余数据,数据的维护成本更高
34.limit 1000000,10加载很慢,怎么解决?
如果id是连续的,可以直接 where id >1000000 limit 10
mysqlselect id, name from emp where id > 1000000 limit 10;
如果id不连接,使用子查询计算id
mysqlselect id, name from emp where id ( select id from limit 1000000, 1 )limit 10;
如果id是索引的话,可以先order by对id排序在limit
mysqlselect id, name from emp order by limit 1000000, 10;
业务上应该避免这么大的分页数
35.drop、truncate、delete的区别
drop
删除整张表,包括数据和结构,属于DDL,不能回滚
truncate
删除表中的所有数据,保留了结构,属于DDL,不能回滚
delete
删除表中的部分数据或者全部数据,逐行删除,速度慢,属于DML,可以回滚
速度方面
drop > truncate > delete
36.union 与 union all的区别
union
union是将俩个结果集进行合并,会去重,同时进行默认规则的排序
union all
union all也是将俩个结果集进行合并,不会去重,包括重复行,不进行排序
union的效率高于union all
37.MySQL的内连接、左外连接、右外连接有什么区别?
内连接
内连接是在俩个表连表查询的时候,只保留完全匹配的结果集
左外连接
连表查询的时候,不但保留完全匹配的结果集还有左表中的所有行
右外连接
连表查询的时候,不但保留完全匹配的结果集还有右表中的所有行
38.常见的聚合函数右哪些?使用聚合函数需要注意什么
avg
sum
count
max
min
注意
聚合函数自动忽略空值
聚合函数在where之后使用,因为where遍历表的时候聚合函数还有算出来结果那
39.一条SQL查询语句的执行顺序
40.索引的优缺点
优点
减少服务器需要扫描的数据量
帮助服务器进行排序和临时表
可以将随机IO编程顺序IO,提高查找性能
缺点
空间角度,创建索引占用物理空间
时间角度,所以的维护代价很高,需要花费时间
41.索引的设计原则
选择经常作为查询条件的列作为索引
为经常需要排序和分组和联合操作的列创建索引
创建唯一性索引
限制索引的数量
小表不建议建立索引
尽量使用前缀索引
删除不再使用或者很少使用的索引
42.索引的使用原则
独立的列
使用前缀索引
使用联合索引
联合索引,把选择性高的列放在前面
合适的主键
不建立重复或者不适用的索引
43.如何判断SQL是否走了索引?
在sql语句前面加explain关键字
44.说一下联合索引
定义
将多个列组合成一个索引,该索引就被成为联合索引
在InnoDB的存储引擎下,默认的索引结构是B+树结构,也就是说非叶子结点存储的是联合索引,叶子节点,存储的是联合索引和主键
满足最左前缀原则
因为联合索引在创建B+树索引的时候,顺序是先按第一个字段排序,如果第一个字段相同再按第二个字段排序。这也就导致了其他字段的顺序依赖于最左边的第一个字段
所以说如果你的where查询条件不是从最左边开始的,就无法使用索引
例如:创建了(a,b,c)的联合索引,你的where 条件 是b c怎么怎么样就无法用到bc索引,因为bc再B+树种是没有顺序的,它依赖于a的顺序
还有就是范围查找后面的字段会索引失效
比如 (a,b,c) where a=1 and b>2 and c = 3;
这种情况就无法使用到了c索引,因为范围查找实际上是按照链表进行遍历,等遍历到b>2的时候,c以及无序了
索引下推
索引下推是在5.6版本以后引入的,目的是在联合索引遍历的过程中,如果第一个字段相同,那么不用回表找第二个字段,直接在联合索引的B+树种就能判断是否满足条件。
索引选择性高的放左边提升查找效率
另外,建立联合索引时的字段顺序,对索引效率也有很大影响。越靠前的字段被用于索引过滤的概率越高,实际开发工作中建立联合索引时,要把区分度大的字段排在前面,这样区分度大的字段越有可能被更多的 SQL 使用到。
区分度就是某个字段 column 不同值的个数「除以」表的总行数,计算公式如下:
比如,性别的区分度就很小,不适合建立索引或不适合排在联合索引列的靠前的位置,而 UUID 这类字段就比较适合做索引或排在联合索引列的靠前的位置。
因为如果索引的区分度很小,假设字段的值分布均匀,那么无论搜索哪个值都可能得到一半的数据。在这些情况下,还不如不要索引,因为 MySQL 还有一个查询优化器,查询优化器发现某个值出现在表的数据行中的百分比(惯用的百分比界线是"30%")很高的时候,它一般会忽略索引,进行全表扫描。
45.索引的优缺点
优点
可以加快查找的效率,使数据有序存储
缺点
索引的创建的需要物理空间的,如果索引特别大的话,那么会占用很大的物理空间
索引的创建和维护都需要时间
增删改会降低表的查找效率,因为这些操作很可能破坏索引的有序性,为了重新实现有序性需要花费时间去维护索引
所以索引不是万能钥匙,是根据场景来使用的
46.什么需要/不需要创建索引?
什么时候需要?
字段又唯一性限制
经常在where条件之后出现的字段,如果有多个字段的话从创建联合索引
经常用于group by或者order by的字段,这样查询的时候就不需要去做一次排序了,因为索引本身就是有序的
什么时候不需要?
字段中存在着大量的重复数据,比如性别不是男就是女,这样的字段选择性太低,无法快速缩小查找范围
表中的数据量很少,不需要创建索引
经常跟新的字段不用创建索引,因为索引的维护代价很大
47.索引优化的方法有哪些?
使用前缀索引优化
对于长度很长的字段如果非要创建索引的话,最好创建前缀索引,就是选该字段的一部分作为索引,但是要保证该部分具有高选择性
使用覆盖索引优化
覆盖索引二级索引查询查询数据的时候,不用回表就查询到想要的数据的一种现场。
主键索引最好是自增的
顺序插入可以减少索引的维护代价,而且可以预防页分裂的现象
索引最好设置为非空
防止索引失效
1.or的左右两边不都是索引
2.where后面的条件是!=这种
3.like '%s' '%s%'
假设你建立了name字段的索引,那么name字段作为索引在B+树上的顺序是有序的,但是如果你不是从第一个字母去比较的话,索引就会失效,因为它变得无序了
4.索引列参与计算了
5.索引列放在函数里面了
6.使用联合索引的时候,没有遵循最左前缀原则