数据库基础部分
数据库的超键、候选键、主键、外键分别是什么?
- 超键:在关系模式中,能唯一标识元组的属性集称为超键。
- 候选键:是最小的超键,没有冗余元素的超键。
- 主键:数据库表中对存储数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的值不能为空。
- 外键:也就是一个表中存在的另一个表的主键。
数据库三大范式?
-
第一范式:表中所有列都不可拆分。
-
第二范式:在第一范式的基础上,表中的列不能依赖主键的一部分,属性完全依赖主键,也就是说一张表完成一件事情。
-
第三范式:属性不依赖与其它非主属性,属性直接依赖于主键
三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。
Mysql基础部分
一条 SQL 是怎么执行的?
这就是考察我们对于 MySQL 数据库架构的知识:
首先客户端先请求连接,数据库连接池建立连接,查询权限,是否合法,然后查询缓存(8.0 版本之前),是否命中,命中就返回,否则进行解析器阶段,解析器阶段主要进行词法分析,分析 SQL 所用到的所有词,再由语法分析器完成 SQL 解析树,然后预处理器去进一步检查解析树是否合法,生成新的解析树,然后进入到查询优化器,或得最优执行计划,之后交给执行器执行查调用存储引擎的接口到磁盘文件中查找并返回数据。
日常中你是怎么优化 SQL 的?
利用索引啦,避免返回不必要的数据行啦,适当的分批量进行,优化 SQL 结构,分库分表啦。
Mysql索引优化部分
你提到了索引,那么介绍一下MySQL 的索引?
索引是帮助 MySQL 高效获取数据的有序的数据结构,排好序的快速查找数据结构。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用指向数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
什么是索引?
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。
索引的目的是什么?
数据量少的时候,其实内存中的全表扫描也不是不快,但是数据多起来得从磁盘中取数据到内存中遍历的话,开销就比较大了,而且io次数不稳定,我们使用mysql的索引可以很大程度上避免io次数不稳定的情况发生。
有了索引可以很大程度上避免数据库进行顺序查找。
SQL 优化的一般步骤是啥?
show status
:用它来了解各种 sql 的执行效率。- 慢查询日志:用它来找到超出系统时间限制的问题 SQL。
explain
:用它来查看这个问题 SQL 的执行计划,然后优化它。- 查看是否涉及多表和子查询,优化 SQL 结构,例如去除冗余字段,是否可以拆表等。
MySQL有什么索引?说一下呗?
- 按数据结构分类:B+tree索引、Hash索引、Full-text索引。
- 按物理存储分类:聚簇索引、二级索引。
- 按字段特性分类:主键索引、唯一索引、普通索引、前缀索引。
- 按字段个数分类:单列索引、联合索引。
什么时候不需要创建索引?
- WHERE,GROUP BY,ORDER BY的条件里用不到字段。
- 在这些情况下,还不如不要索引,因为 MySQL 还有一个查询优化器,查询优化器发现某个值出现在表的数据行中的百分比很高的时候,它一般会忽略索引,进行全表扫描。
- 表数据很少的话也不需要。
- 经常更新的字段不用,不然容易引起索引的频繁重建。
MySQL 索引为什么选择 B+ 树?
因为从从没有索引开始,得全表遍历,但是数据越来越多,那么时间开销就会越来越大,这种情况下,我们就得建立一种数据结构,一种能够快速有效的通过映射来查询数据的数据结构,这就是 MySQL 中的索引。
首先我们想到普通二叉树,但是由于特殊情况,普通二叉树会变成一个链表,那和全表遍历效率没啥区别,那么使用哈希表呢?哈希表虽然查询速度优秀,但是它不能支持范围查询啊。所以我们开始使用一些特殊树结构,用红黑树,它的查找范围和查找速度都十分优秀,但是,如果数据特别大,那么这棵红黑树的结构也会特别大,深度不可控,所以,我们此时的重点就在找到一个可控深度的,支持范围查询的,查询时间稳定的数据结构,但是这样的数据结构,往往还是有一定的缺点,比如每次更新树结构的代价都很大。
B-tree
就来了,它是一棵绝对平衡的多路树,深度可控,但是,查询效率可能还是不太稳定,他虽然控制了最大深度不会过深,但是会面临I/O次数 <= 最大深度的情况,某种意义上来说,还是I/O次数不稳定,只是控制了最大深度罢了。如果数据量大的话,I/O次数不稳定带来的也许是未知的风险。
所以,我们就又得找在 B-tree
的基础上,I/O次数更加稳定的一种数据结构,所以就改造出来了 B+tree
,这种树呢所有的子节点都不存放数据,所有数据都存在叶子节点上,那么 I/O 次数,相对于 B-tree
更稳定了,相邻叶子节点间还用了双向链表连接,所以范围查询更加简便,效率更高,而且,如果非叶子节点不存储数据的话就意味着可以存储更多的键值,树就会更矮更胖,所以 MySQL 选择使用 B+ 树作为索引
每个结点都作为一个磁盘页
那为啥要用B+树而不是跳表呢?
首先,我们从时间的角度上来说,跳表比B+树出现的晚,其次,我们都知道,一个B+树按照页内存16KB并且索引是int的话,B+树叶子节点大概能装2kw数据,2的24次方左右;
跳表是链表结构,一条数据一个结点,如果最底层要存放2kw数据,且每次查询都要能达到二分查找的效果,2kw大概在2的24次方左右,所以,跳表大概高度在24层左右。最坏情况下,这24层数据会分散在不同的数据页里,也即是查一次数据会经历24次磁盘IO,这带来了IO次数不稳定的情况,而同样情况下,B+树的IO次数恒定在3次。
所以跳表是否新增层数,全靠它的随机函数,这图中的随机函数就随机到了第三层也要新建节点,所以在每一层都插入这个节点了。
理论上来说,我们磁盘IO的次数越小,访问速度越快,所以Mysql选择了B+树。
换个方向来说,写操作有些情况下B+树需要拆分节点再合并,肯定没有跳表直接随机函数插入快,因为不用保持平衡。
B 树和B+ 树 的区别能说一下吗?
上面那题回答得很清楚了:
- 前者查询次数不稳定,后者更加稳定。
- 前者范围查询没有后者范围查询高效。
- 前者每个结点都有数据,后者只有叶子节点存放数据。
聚簇索引与非聚簇索引的区别说一下呗?
- 一个表中只能拥有一个聚集索引,非聚集索引可以存在许多个。
- 聚簇索引,索引中的键值的逻辑顺序决定了表中相应行的物理顺序;非聚簇索引,索引中索引的逻辑顺序与磁盘上行的物理存储数据不同。
- 索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据结点;而非聚簇索引的叶节点仍然是索引结点,只不过有一个指针指向对应的数据块。
- 聚簇索引就是物理存储按照索引排序,非聚簇索引就是物理存储不按照索引排序。
使用索引的注意事项?
- 尽量满足最左前缀法则。
- 小表驱动大表。
- 如果是字符串,记得打单引号,避免类型转换带来的失效。
- 查询条件包含
or
可能会失效。 like
通配符百分号在前的都会失