1.主键索引与唯一索引有什么区别?
-
主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;
-
主键不允许为空值,唯一索引列允许空值;
-
一个表只能有一个主键,但是可以有多个唯一索引;
-
主键可以被其他表引用为外键,唯一索引列不可以;
-
主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别
2.索引数为什么用B+Tree而不是B Tree?
因为B*树非叶子节点使用了指向兄弟节点的指针。
如果一个节点满了之后,自己的兄弟节点还没有满,
需要将一部分数据转移到自己的兄弟节点去。
如果兄弟节点也满了,就在自己和兄弟节点之间添加新的节点。
因为兄弟之间分配新节点的概率还是比较低的,所以空间利用率还是比较高的。
是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
3.索引结构为什么要设计为树形?用Hash可以吗?
对于这样一个单行查询的SQL需求:
select * from t_users where name='nange';
确实是哈希索引更快,因为每次都只查询一条记录。
画外音:所以,如果业务需求都是单行访问,例如passport,确实可以使用哈希索引。
但是对于排序查询的SQL需求:
分组:group by
排序:order by
比较:<、>
哈希型的索引,时间复杂度会退化为O(n),而树型的“有序”特性,依然能够保持O(log(n)) 的高效率。
4.where in (几个) where in (几万个) 有什么区别
select * from single_table where key1 in ('aa', 'aa1', 'aa2', ..., 'zz100');
mysql在5.7.3之前的版本是的eq_range_index_dive_limit的默认值是10,在5.7.3之后是200.
当in语句的单点区间数量大于等于eq_range_index_dive_limit的值时,就不会使用index dive来计算各个单点区间对应的索引记录条数,而是使用索引统计数据。
例如rows是9693,key1列的不重复值为968,所以key1列的平均重复次数为:9693/968 = 10条。
当in的数量为20000个时,意味着有20000个单点区间的时候,就直接使用统计数据来估算对应的记录条数。每个区间对应10条,对应的回表记录数就是20000 * 10 = 200000条。
当in的数量为几个的时候,由于key1列只是一个普通索引的话,每个单点的值对应多少条记录并不确定。计算方式就是直接获取索引对应的B+树的区间最左记录和区间最右记录,然后再计算这两条记录之间有多少条记录。
这种直接访问索引对应B+树来计算某个扫描区间内对应的索引记录条数的方式就是index dive
5.什么是脏读?
当数据库中一个事务A正在修改一个数据但是还未提交或者回滚,
另一个事务B 来读取了修改后的内容并且使用了,
之后事务A提交了,此时就引起了脏读。
此情况仅会发生在:读未提交的的隔离级别.
6.描述下事务隔离级别?
-
读未提交:就是他能读取到别人未提交的内容。可以读取到未提交的内容。【会出现脏读的情况】
-
读提交;也就是只能读取到别人提交后的内容。别人提交后才能读。
【会出现不可重复读的情况】
-
可重复度:就是前后读取时一致的。事务执行过程中的数据,
跟执行后读取到的数据是一致的。【会出现幻读的情况】
-
串行化:就是事务吧,这种的话,就是效率会比较慢。
写会加写锁,读会加读锁。读写冲突的时候,必须等到前一个事务结束之后,才能之后后一个事务。(加锁, 来避免访问。)
【会出现超时和锁竞争的情况】
7.如何优化慢SQL?
-
数据库CPU负载高。一般是查询语句中有很多计算逻辑,导致数据库cpu负载。
-
IO负载高导致服务器卡住。这个一般和全表查询没索引有关系。
-
查询语句正常,索引正常但是还是慢。如果表面上索引正常,但是查询慢,需要看看是否索引没有生效。
解答思路:针对SQL语句的优化,我们不要一上来就回答添加索引,
这样显得太不专业。我们可以从如下几个角度去分析:
-
回归到表的设计层面,数据类型选择是否合理。
-
大表碎片的整理是否完善。
-
表的统计信息是不是准确的。
-
审查表的执行计划,判断字段上面有没有合适的索引。
-
针对索引的选择性,建立合适的索引(就又涉及大表DDL的操作问题。所以说,我们要有能力把各个知识点联系起来)