《剑指Java面试-Offer直通车》视频学习笔记--数据库

数据库

一、如何设计一个关系型数据库?

数据库最主要的功能是存储数据,因此有一个存储模块存储数据。存储模块类似OS文件系统,将数据持久化存入磁盘中,如存入机械硬盘、SSD固态硬盘、亦或者是它们的磁盘阵列矩阵中。

但是只有存储是不行的,还需要组织并且用到这些数据,因此需要有程序的实例,用逻辑结构来映射出物理结构,并且在程序中提供获取和管理数据的方式,以及提供必要的问题追踪机制。

细分程序模块:

1)数据逻辑关系转换成物理存储关系的存储管理模块:首先对数据的格式和文件的分隔进行统一的管理,即把物理数据通过逻辑的形式组织表示出来,便涉及到程序的存储管理模块。(优化存储效能:处理数据不在磁盘上做,而是加载到程序空间所在内存里,磁盘IO速率是程序执行速率的主要瓶颈,远差于内存的执行效率。为了执行效率,要尽可能减少IO。就存储管理而言,如果按照逐行查找并返回,频繁的IO会使数据库的执行效率慢。因为一次IO读取单条数据和多条数据没有太大的区别,所以可以一次性的读取多行,以提升IO的效能。行就失去了意义,数据以块和页作为逻辑存储单位,每个块和页中存放多行数据,读取的时候将多个块和页加载进内存中。)

2)优化执行效率的缓存模块:为了更快更好的优化利用内存,可以利用缓存机制,把取出来的数据块放进缓存里,下次需要的时候直接从内存返回,而不用发生IO。一次性加载多个模块或者页,块里包含的数据行有数据可能不是我们本次查询需要的行,但是一旦某行数据被访问了,它周围的数据也极有可能被访问的经验,缓存的非本质数据也能起到优化访问效率的作用,提升访问的性能。管理缓存的方法有LRU等。

3)将SQL语句解析的SQL解析模块:提供外部指令操纵数据,即可读的SQL语言,需要SQL解析模块将SQL编译解析,转换成机器可识别的指令。这时为了进一步提升SQL的执行效率,将SQL缓存到缓存里直接解析。缓存不宜过大,且有算法里淘汰机制,淘汰掉之后不常用的数据。

4)记录操作的日志管理模块:SQL操作需要记录下来,方便数据库的主从同步或者灾难恢复,因此需要日志管理对操作进行记录,如binlog的记录方式。

5)多用户管理的权限划分模块:还需要提供给用户管理数据的私密空间,即权限划分。通俗将就是老板可以看到员工的数据,员工只能看到自己该看到的数据。权限划分是DBA做的。

6)灾难恢复模块:除了考虑正常情况,还需考虑异常情况,需要引入异常机制,即容灾机制。当数据库挂了如何恢复,恢复到什么程度。

7)优化数据查询效率的索引模块和使得数据库支持并发操作的锁模块:为了进一步提升查询数据的速度以及让数据库支持并发,需要引入索引和锁模块。

 

二、索引模块

  • 为什么要使用索引?

快速查询数据

(最简单的方式实现数据查询,即全表扫描,将整张表的数据全部或者分批次加载到内存中。存储的最小单位是块或者页,他们是由多行数据组成。将块加载进来,逐个块轮询,找到目标并返回。这种方式普遍比较慢。很多情况下都要避免全表扫描情况的发生,所以数据库引入更高效的机制,即索引。关键信息和查找信息的方式组成索引,通过索引可以大幅提升查询速度。)

  • 什么样的信息能成为索引?

主键、唯一键、普通键

(把记录限定在一定查找范围内的字段,主键便是一个很好的切入点,其他包括唯一键、普通键等也可以作为索引。)

  • 索引的数据结构?

生成索引,建立二叉查找树进行二分查找。

生成索引,建立B-Tree结构进行查找。

生成索引,建立B+-Tree结构进行查找。

生成索引,建立Hash结构进行查找。

(让查询变得高效的数据结构,如二叉查找树和二叉查找树的变种平衡二叉树、红黑树、BTree、B+Tree以及Hash结构。MySQL数据库索引是通过B+Tree实现。)

三、优化索引

  • 利用二叉查找树

二叉查找树是每个节点最多有两个子树的树结构,通常子树被称为左子树或右子树。左子树节点的值均小于根节点,右子树节点的值均大于根节点(注意索引的存储块和数据库的最小存储单位块或者页并非一一对应,为了方便理解先一一对应起来)。每个存储块存储的是关键字和指向子树的指针。平衡二叉树任意一个节点的左子树和右子数高度差不超过1。

查询时间复杂度O(logn),查询效率高。极端情况(节点全部在左子树或右子树上)时间复杂度将为O(n)。可以利用树的旋转的特性保持树为平衡二叉树。但还有另一个问题,影响程序运行速度的瓶颈是IO。如果假定索引块在磁盘中,找索引会先发生一次IO,将数据读入内存中,之后再发生IO继续查找,直到找到。检索深度每增加1,就发生一次IO。平衡二叉树、红黑树等每个节点只能有两个孩子。为了组织起数据块,树的深度很深,IO的次数也会很多,检索性能没法满足优化查询需求。

即降低查询的时间复杂度,又降低IO的次数,要让树每个节点能承受的数据多一些,即利用B-Tree、B+-Tree。

  • 利用B树

B树,即平衡多路查找树。每个节点最多有m个孩子,这样的树即为m阶B树。每个存储块主要包含关键字和指向孩子的指针,最多能有几个孩子取决于每个存储块的容量和数据库的相关配置(通常情况下m是很大的)。

B树特征:

1)根节点至少包括两个孩子。

2)树中每个节点最多含有m个孩子(m>=2)。

3)除根节点和叶节点外,每个节点至少有ceil(m/2)个孩子。ceil向上取整

4)所有叶子节点位于同一层。

5)假设每个非终端节点中包含有n个关键字信息,其中:

    a)Ki(i=1...n)为关键字,且关键字按顺序升序排序K(i-1)<K(i)。

    b)关键字的个数n必须满足:[ceil(m/2)-1]<=n<=m-1。(任意节点的关键字个数上限比它的孩子数上限少一个,且对于非叶子节点来说,任何一个节点的关键字个数比指向孩子的指针数少一个)

    c)非叶子节点的指针:P[1],P[2]...P[M],其中P[1]指向关键字小于K[1]的子树(某节点最左边孩子节点关键字的值均小于该节点最左边关键字的值),P[M]指向关键字大于K[M-1]的子树(某节点最右边孩子节点的关键字的值均大于该节点里所有关键字的值),其他P[i]指向关键字属于(K[i-1],K[i])的子树(某节点其余孩子节点关键字的值的大小均位于离该孩子节点指针最近的两个关键值之间)。

查找效率和二叉查找树一样,为O(logn)。B树通过合并、分裂、上移、下移节点保持特征,使树比二叉树矮,数据不断变动后不会变成线性的。

B树示例:

  • 利用B+树

B+树是B树的变体,其定义基本与B树相同,除了:

1)非叶子节点的子树指针与关键字个数相同。(B+树能存储更多的关键字)

2)非叶子节点的子树指针P[i],指向关键值(K[i],K[i+1])的子树。(K[i]指向的子树,均小于关键字K[i+1]的值)

3)非叶子节点仅用来索引,数据都保存在叶子节点中。(B+树所有的检索都是从根部开始,检索到叶子节点结束,非叶子节点仅存储索引不存储数据,能存储更多的数据。B+树相对B树更矮。B树的搜索可能在任何一个非叶子节点就终结掉了。)

4)所有叶子节点均有一个链指针指向下一个叶子节点并按大小顺序链接。(支持范围统计,即定位到某个叶子节点便可以从该叶子节点开始横向跨子树统计。)

B+树示例:

B+树更适合用来做存储索引:

1)B+树的磁盘读取代价更低(B+树内部结构没有指向关键字具体信息的指针,不存放数据,只存放索引信息。内部节点相对B树更小。如果把所有内部节点的关键字存放在同一盘块中,盘块能容纳的关键字数量也越多,一次性读入内存查找的关键字也就越多,相对来说IO读写次数低)。

2)B+树的查询效率更加稳定(内部节点不是指向文件内容的节点,只是叶子节点中关键字的索引,任何节点的查找必须有一条从叶子节点到根节点的路,所有关键字查询的长度相同,每个数据的查询时间相同,O(logn))。

3)B+树更有利于对数据库的扫描(B+树只需要遍历叶子节点就可以解决对全部数据的扫描)。

发布了22 篇原创文章 · 获赞 7 · 访问量 4471

猜你喜欢

转载自blog.csdn.net/lucky_jiexia/article/details/105356483