数据库系统概念之存储和文件结构

物理存储介质

  1. 高速缓冲存储器(cache):也称为高速缓存,最快最贵的介质,最靠近CPU,常见的L1,L2,L3
  2. 主存储器(main memory):也称为内存,掉电会丢失数据
  3. 快闪存储器(flash memory):掉电不丢失数据,数据存取速度比磁盘块,有两种类型,NAND和NOR快闪,快闪顺序访问和随机访问速度接近都很快,闪存写入一个闪存页面只需几微秒,但是写之前如果要擦除需要1-2毫秒,闪存可擦除次数有限制。闪存转换层(flash translation layer)可以让其均匀擦除称为损耗均衡(wear leveling),并且通过映射逻辑页面到物理页面,可以在写入时先写入另一个已被擦除的物理闪存页面,之后再擦除该物理闪存页面,提高写入效率
  4. 磁盘存储器(magnetic-disk storage):掉电不丢失数据,但速度较慢,价格便宜
  5. 光学存储器(optical storage):即光盘CD(Compact Disk)可以容纳700MB数据,数字视频光盘DVD(Digital Video Disk),每一盘面可以容纳4.7GB或8.5GB数据,按照读写模式,分为只读光盘CD-ROM和只读DVD(DVD-ROM),写一次读多次CD-R和DVD-R和DVD+R,写多次读多次CD-RW和DVD-RW和DVD+RW和DVD-RAM
  6. 磁盘存储器(tape storage):磁盘具有很大容量(40G-300G),但是无法随机访问,只能顺序访问

磁盘存储器

磁盘组成

  1. 盘片:一个磁盘一般有1~5个盘片
  2. 盘面:一个盘片有两个盘面
  3. 磁道:盘面上每一环(半径不同的同心圆)都是一个磁道,一个盘面50000~100000条磁道
  4. 扇区:磁道上的圆弧就是扇区,扇区大小一般为512字节,扇区是磁盘读取和写入的最小单位,内层磁道包含500-1000个扇区, 外层磁道包含1000-2000个扇区
  5. 柱面:由于一个磁盘有多个盘片,一个盘片有两个盘面,而盘片是绕着主轴旋转的,有固定不动的磁盘臂,这个磁盘臂不止一个读写头,因为它要同时读写所有盘面,所以就将所有盘面上的同一条磁道组成的柱状叫做柱面,这些磁道只是竖直方向不重叠,柱面数等于一个盘面上的磁道数,柱面是虚拟的,不是真实存在的

坏扇区的重映射(remapping of bad sector)

  1. 当磁盘初始格式化时,或试图写一个扇区时,如果磁盘控制器检测到一个损坏的扇区,它会把这个扇区在逻辑上映射到另一个物理位置,等下次写该逻辑位置就会写另一个物理位置
  2. 根据上面有个思考,上面的解决方案只能解决从未写入的扇区的数据丢失,无法防止已经写入的扇区的数据丢失,

磁盘性能度量

  1. 容量:磁盘容量,一般以字节衡量,只不过厂商的单位是1KB = 1000B,而我们电脑的计算单位是1KB=1024B,所以买回来的磁盘总是缺斤少两,多提一下,计算机网络里面的速率全是1000来衡量,没有1024
  2. 访问时间(access time):从发出读写请求到数据开始传输之间的时间,包括启动时间和寻道时间还有旋转等待时间
  3. 寻道时间(seek time):磁盘臂重定位到要取数据的磁道的时间
  4. 平均寻道时间(average seek time):平均寻道时间是最长寻道时间的二分之一,一般在4-10毫秒之间
  5. 旋转等待时间(rotational latency time):在找到对应磁道后,需要等待盘面旋转,直到读写头碰到要读写的扇区
  6. 平均旋转等待时间:该时间为盘面旋转一周的时间的一半
  7. 数据传输率:每秒传输的字节数量
  8. 可靠性:一般可以用平均故障时间(Mean Time To Failure)来度量

磁盘块访问优化

  1. 访问方式:顺序访问(sequential access)比随机访问(random access)快很多
  2. 缓冲(buffering):从磁盘读取的块暂时存储在内存缓冲区,以后很有可能再次用到(时间局部性)
  3. 预读(read-ahead):当一个磁盘块访问时,相同磁道的连续块也被读入到内存缓冲区中(空间局部性)
  4. 调度(scheduling):从上面的访问时间来看,只有里面的寻道时间可以用算法优化,通常使用电梯算法(elevator algorithm),即从内端磁道扫描到外端磁道,再从外端扫描到内端磁道,这种调度算法被称为SCAN算法,针对SCAN改进后的LOOK算法是当一个方向上没有请求直接调转方向,扫描算法类似的调度算法还有最短寻道时间优先,先来先服务,优先级调度(实时调度,引入时间限制),优先级调度包括最早截止期优先EDF(Earliest Deadline First),SCAN-EDF是先按照最早截止期优先,相同截止时间按照SCAN扫描算法,PI(Priority Inversion)算法将请求队列中的请求分成两个优先级,先处理高优先级的,FD-SCAN(Feasible Deadline SCAN)算法,首先从请求队列中找出时限最早,从当前位置开始移动又可以满足其时限要求的请求,作为下一次SCAN的方向,如果从当前位置移动过去还是不能满足要求,就放弃该任务
  5. 文件组织:操作系统应当将一个文件的多个物理块尽量连续分布,实际上操作系统将文件分成多个连续的块,保证局部顺序来提高效率。在经过多次修改后文件可能变得碎片化(fragmented),可以扫描整块磁盘移动(复制)磁盘碎片让它们连续,用来提高访问效率
  6. 非易失性写缓冲区(nonvolatile write buffer):因为内存掉电丢失数据所以我们需要将数据写到磁盘,可以使用非易失随机访问存储器(Non Volatile Random-Access Memory)来加速写磁盘的操作,即保存一定量的数据,然后一次性写入磁盘,而且又不用担心掉电丢失数据
  7. 日志磁盘(log disk):磁盘顺序写入日志(顺序写性能很快),然后再写入数据,数据可以先放在内存里面,不用着急写入磁盘,等空闲的时候再写入,就算内存数据丢失,操作系统也可以根据磁盘中的日志恢复数据

独立磁盘冗余阵列RAID(Redundant Array of Independent Disk)

独立磁盘冗余阵列作用

  1. 通过冗余提高可靠性:可以将一个磁盘复制两份,这样就算丢失或损坏一个磁盘另一个磁盘也可以备用,这种称为镜像,采用镜像的技术的磁盘的平均数据丢失时间(mean time to data loss) = 平均故障时间 × 平均故障时间 / 2 × 平均修复时间(mean time to repair),2是两个磁盘,平均修复时间是替换发生故障的磁盘并且恢复这张磁盘上的数据所花费的时间。镜像技术虽然好,但是很浪费空间,可以只备份一些纠错码,等丢失数据时,根据纠错码和现有数据恢复磁盘
  2. 通过并行提高性能:可以通过数据拆分(striping data)来提高传输速率,常见的有比特级拆分(bit-level striping),将数据的每一个字节中的8位拆分到8张磁盘中,所以阵列中磁盘数量必须是8的倍数,读取数据的时候可以8张磁盘并发读取。块级拆分(block-level striping),将文件分块,每块存储在一个磁盘中,这个不要求磁盘数量,只需要用块编号堆磁盘总数取余,就知道每块放在哪个磁盘了

RAID级别

  1. RAID 0 级 (无冗余拆分):使用块级拆分,没有任何冗余,提高性能,但可用性差
  2. RAID 1 级 (镜像磁盘):使用块级拆分,使用镜像冗余,每张磁盘都有镜像,可用性高,性能好,镜像也可以用来并发读取和写入,但是存储空间占用大,
  3. RAID 2 级 (内存风格纠错码):加入奇偶校验码,内存中每个字节都有1位用于奇偶校验。这个等级每4张磁盘需要三张用于存储纠错码,因为使用汉明码来进行纠错,汉明码为4位数据进行纠错时需要3位纠错码
  4. RAID 3 级 (位交叉奇偶校验):使用比特级拆分,每4张磁盘要多使用一张用于存储奇偶校验码,为每4位数据存储1位的冗余信息,该奇偶校验码是根据四张磁盘上的同一位来计算的,如果丢失或损坏其中一个磁盘,可以通过其他所有磁盘来恢复,就是恢复时间比镜像拆分长
  5. RAID 4 级 (块交叉奇偶校验):使用块级拆分,每4张磁盘要多使用一张用于存储奇偶校验码,为每4位数据存储1位的冗余信息,其实计算奇偶校验码还是按照位的单位来计算的,只是拆分方式是块级。如果丢失或损坏其中一个磁盘,可以通过其他所有磁盘来恢复,就是恢复时间比镜像拆分长
  6. RAID 5 级 (块交叉的分布奇偶校验):使用块级拆分,每4张磁盘要多使用一张用于存储奇偶校验码,为每4位数据存储1位的冗余信息,上面两个是将校验码存储在单一磁盘,这个是分散存储在各个磁盘中
  7. RAID 6 级 (P + Q 冗余):使用块级拆分,每4张磁盘要多使用两张用于存储奇偶校验码。因为它使用Reed-Solomon码来进行纠错,提高非常高的可用性,为每4位数据存储2位的冗余信息

RAID级别的选择

考虑因素

  1. 所需的额外存储空间
  2. 在I/O操作方面的性能
  3. 磁盘故障时候的性能
  4. 磁盘重建过程所需时间

适用场景

  1. RAID 0 用于数据安全性不是很重要的高性能应用,因为有拆分但无冗余
  2. RAID 1 有拆分也有冗余,性能好,安全性好,恢复速度块,磁盘故障时几乎无影响,因为可以随时切换,而其他的所有级别都需要恢复后再访问磁盘
  3. RAID 2 使用纠错码太多,RAID虽然使用汉明码,但是数据也是拆分了的,把汉明码的纠错码也按位拆分到不同磁盘
  4. RAID 3 使用比特级拆分,虽然性能高,但是一个小文件也需要所有磁盘一起传输,所以阵列中能支持的并发IO数量比较小,而且磁盘访问时间比数据传输时间长很多,多张磁盘都需要磁盘访问,所以需要时间更多
  5. RAID 4 使用块级拆分,在大文件上和比特级别传输速度相同,而且在小文件上只需其中某个磁盘进行传输就行
  6. RAID 5 使用分布式的奇偶校验码,是RAID 4的改进版
  7. RAID 6 虽然安全性很高,但是现在许多RAID实现还不支持这种级别
  8. 一般只在RAID 1 和 RAID 5 进行选择,当磁盘空间成为主要难题时选择RAID5,当磁盘空间充足时选择RAID 1

硬件问题

  1. 位腐(bit rot):指的是在之前写入数据成功,一般写入后磁盘都会读取一次看是否写入成功,但是在写入后可能因为制造缺陷或相邻轨道重复写入时发生数据损坏,这样丢失的数据是先前成功写入的,也称为潜在故障(latene failure)
  2. 擦洗(scrubbing):为了解决上面问题,RAID控制器会在磁盘空闲期间对每一个扇区进行读取,如果无法读取就调用其他磁盘进行恢复
  3. 热交换(hot swapping):一些硬件RAID允许在不切断电源的情况下将出错的磁盘用新的磁盘替换

文件组织

一个数据库被映射到多个不同的文件,这些文件由底层操作系统来维护。一个文件上在逻辑上组织成为记录的一个序列,但是在物理上却是分块进行映射的,在数据库中每块为4-8KB,这是8-16个扇区,在微软操作系统中磁盘文件存储管理的最小单位叫做簇,每个簇为2或4或8或16或32或64个扇区,即2的次方倍个扇区。以下文件组织都是逻辑上的,因为数据库的文件组织其实离存储器还隔着一层操作系统

记录(表中的行)构成

定长记录

  1. 由于里面的属性(字段)定长所以直接无缝隙紧密存储(逻辑上的,物理实现一般局部有序),这里直接就解决了记录内部的属性如何存储
  2. 对于定长记录在文件中存储可以直接采用紧密排列,紧密排列虽然添加记录(表中的行)容易,但是删除需要移动很多记录,类似数组(这里是对整个记录的组织,不再是其内部属性了)
  3. 引入链表结构,在文件的开始处分配一定数量的字节作为头文件,头文件存储有关文件的各种信息,还可以存储指向第一个被删除的记录的地址,而第一个被删除的记录又存储着下一个被删除的记录的地址,如果没有被删除的记录,这样在被删除的记录之间就构成了一个链表,就可以快速删除和替换记录了

变长记录

  1. 表中有可能有变长字段,如varchar,所以会有变长记录
  2. 变长记录(记录也叫行),需要存储的是定长属性(属性也叫字段)和变长属性,对于定长属性直接按其长度存储,对于变长属性,需要存储两个值,偏移量和长度
  3. 定长记录的结构是一开始存储偏移量和长度,都用两个字节表示,所以每有一个变长属性,就需要4个字节的初始块,在初始块后面直接就是定长属性,然后是空位图,一个字节的位图可以表示8个属性是否为空值,位图后面就是变长属性
  4. 位图记录的顺序是相反的,一条记录(行)最后一个属性在位图的位置是第一位

总结

  1. 上面描述是一条记录(行)内部是由什么组成的,以及内部属性是怎么组织的,下面是用于在一个块(页)中组织多条记录的方式,块(页)是定长的,一个文件由许多(页)组成
  2. 就记录而言,如果是定长记录可以使用上面描述的紧密排列和链表方法就可以将记录存放在文件中,如果记录是变长记录(里面有变长字段),就需要使用分槽的页结构了
  3. 页是定长的,可以想象由于文件无法有效组织变长记录,可以先将其包装成定长的页,然后再用页去组成文件
  4. 为什么说文件无法有效组织变长记录呢,如果像变长记录组织其内部的变长属于一样使用偏移量和长度两个值的话,如果想读取文件中的记录,必须将文件全部读取到内存中,因为偏移量和长度在头部,有些数据在尾部。有时文件很大,无法一次读取内存中
  5. 所以可以通过分页,页固定长度而且比较小,固定长度表明无须使用偏移量和长度,可以直接随机读取,因为可以根据固定长度乘以页号就知道它在哪个位置了

分槽的页结构(slotted-page structure)

这里描述的是块(页)怎么组织其内部的记录的

  1. 每个块包含一个块头,块头有三个信息,块头中记录条目的个数,块中空闲空间的末尾处(地址)和一个由包含记录位置和大小的记录条目组成的数组
  2. 可以看到块把记录全部当初变长记录,每个记录都有位置(偏移量)和大小(长度)
  3. 而且第一个记录是在块的尾部,从尾部开始填充记录,中间的是空闲空间
  4. 虽然删除记录会移动记录让它们紧密排列,但是由于块一般只有4-8KB,所以移动的代价不高,还需要修改空闲空间末尾指针(这个是真正的指向空闲空间末尾处,而不是条目,和下面不一样)和将块头的对应记录大小修改为-1
  5. 分槽的页结构的指针不直接指向记录,而是指向记录位置和大小的条目,这样就可以放心移动记录了,而不用再改变指针指向

文件组织

顺序文件组织

  1. 对于定长记录,可以使用顺序文件组织,顺序文件组织是指按照搜索码(主键索引列)对记录进行排序,然后顺序存储,顺序文件组织分为两种,数组型顺序,链表型顺序,定长记录两种都可以使用,但是数组型顺序插入和删除不方便,需要移动很多记录,所以一般使用链表形式存储
  2. 对于变长记录,也可以使用顺序文件组织,但是只能使用链表实现,每个记录最后的部分存储着下一个记录的地址,插入和删除也很方便,只需要修改地址就可以了,但是有个缺点虽然记录逻辑上有顺序,但是物理上却不相邻,所以进行逻辑上的顺序访问效率可能会越来越低,所以这个时候文件应当重组(reorganized),把记录按照搜索码的顺序在物理上进行重新排序

多表聚簇文件组织

  1. 多表聚簇文件组织是指在一个文件中的一个块中存储多张表的记录,这样如果把需要进行关联(多表查询)的记录存放在一起,表关联查询的时候就只需要访问一个物理块了,不用访问多个物理块
  2. 多表聚簇文件组织虽然对性能提高有很大好处,但实现比较复杂,很多关系数据库系统都将每个表存储在单独的文件中

大对象的文件组织

  1. 数据库可能要存储一些比磁盘块大得多的数据,如图片或视频
  2. 这种就是数据库支持的二进制长对象blob(binary long object)和字符长对象clob(character long object)
  3. 这种大对象无法一下查询出来,也无法放在记录中,只能在记录中存储指向改大对象的指针(地址),根据偏移量和长度来慢慢读取

堆文件组织

一条记录可以放在关系的任何地方,只要要那个地方有空间存放这条记录。记录是没有顺序的,通常每个关系使用单独的文件

散列(hash)文件组织

将每条记录的某些属性通过一个散列函数计算出该记录存储在文件中的哪个块(块是数据库最小读取单位,簇是操作系统文件系统最小读取单位,扇区是磁盘物理最小读取单位,一个块或簇对应多个扇区)

索引文件组织

  1. 有两种一种是单独建立B+树索引文件,B+树节点中存储指针(地址),指向对应记录的块
  2. 另一种是直接使用B+树来组织文件,B+树节点存储的是记录的块

数据字典存储

  1. 上面我们只考虑数据本身,也就是记录本身,那记录(元组)的每个部分的含义,以及一些表的配置都会产生一个数据,这种关于数据的数据称为元数据(metadata)
  2. 关于关系(表)的关系模式(表结构)和其他元数据存储在称为数据字典(data dictionary)或系统目录(system catalog)的结构中
  3. 系统必须存储的信息类型有:
  4. 表的名字,每个关系中属性的名字,属性的域和长度,在数据库上定义的视图的名字和这些视图的定义,完整性约束(主键、外键、唯一、非空、check检查约束、default默认约束),
  5. 授权用户的名字,关于用户的授权和账号信息,用于认证用户的密码或其他信息,
  6. 每个表中的元组(行)总数,每个表所使用的存储方法(聚簇或非聚簇表组织)
  7. 每个表的存储文件和在文件中的位置,如果所有表存储在同一文件中,则还需要包含每个关系的记录()行的块存储在链表的数据结构,因为所有表都在同一文件,必须要有一个数据结构用来区分一个文件哪些位置是哪个记录,属于哪张表
  8. 索引的名字,被索引的关系的名字(定义索引的表),在其上定义索引的属性(定义索引的列),构造的索引的类型(Hash索引、B+树索引)

缓冲区

缓冲区(buffer)是在主存储器(内存)中用于存储磁盘块的拷贝的那一部分

缓冲区管理器

  1. 负责管理内存的缓冲区的称为缓冲区管理器(buffer manager)
  2. 数据库缓冲管理器和操作系统缓冲管理器的类似,但是策略上有很大不同
  3. 在数据库缓冲管理器上有被钉住的块(pinned block)的概念,即一个块在更新操作正在进行时,大多数数据库缓冲管理器不允许将其写回磁盘,因为需要进行事务控制,在写数据块之前必须将日志全部写入磁盘,之后才能写入数据块,而操作系统缓冲管理器一般不会这样,因为在操作系统的角度,不管是日志还是数据块缓存都只是文件中的数据而已两者没有差别
  4. 操作系统缓冲管理器只有一个策略,就是将未来不使用或最少使用的块置换处内存就行,能达到这种要求的算法是最佳置换算法OPT(Optimal),这种算法无法实现因为无法预测未来,但是有近似实现,如最近最久未使用LRU(Least Recently Used)置换算法
  5. 其他的页面置换算法(内存置换算法)有Clock置换算法(LRU算法的近似实现,实现简单开销小),最少使用LFU(Least frequently used)置换算法,最近未使用NRU(Not Recently Used)置换算法,第二次机会算法(分为FIFO队列第二次机会算法和Clock第二次机会算法),工作集算法(指的是一次读取不再是一个块,而是整个工作集),工作集时钟算法(置换的单位从一个块变成一个工作集)。一个进程当前正在使用的页面的集合称为它的工作集,如果不使用工作集算法,可能将一个进程的部分页面反复置换出去,但其实该进程还是需要这些页面的,但是使用了又会浪费空间,因为有些页面进程可能只使用一次,用完就再也不用,如顺序读取文件并修改再写回
  6. 在数据库缓冲管理器上还有块的强制写出(forced output of block)的概念,尽管不需要一个块所占用的缓冲区空间,但必须把这个块写回磁盘,为了数据能够在断电时不丢失,而操作系统一般是等内存不够的时候才启用页面置换算法(内存置换算法)

缓冲区替换策略

  1. 数据库缓冲替换策略和操作系统的有很大不同,因为目的不一样
  2. 考虑到有两张表进行联接查询,可以把它们想象成,两层for循环,外层for循环是遍历第一张表的元组,内层for循环是遍历第二张的表的元组,所以第一次数据库会读取第一张表的第一个元组,而内层for循环会读取第二张所有元组
  3. 根据上面第一张表适合的缓冲区置换策略是立即丢弃策略(loss-immediate),因为用过的元组在这次联接查询中不会再次用到,而第二张表的内存置换策略应该是最近最常使用MRU(Most Recently Used),因为刚刚使用过的元组,只有到下一次循环才被使用,而距离当前以及最不常使用的块,很可能将要被使用,这和操作系统LRU策略相反
  4. 上面的描述都是逻辑上的,其实具体实现,如果两张表有外键索引,则数据库会循环遍历后面语句的table2,并对table1使用索引,select * from table1, table2;

参考

《 数据库系统概念 》

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lolxxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值