10.内存层级和文件组织

磁盘和文件

  • DBMS 将信息存储在(“硬盘”)磁盘上
    • 磁盘是一个序列字节,每个字节都有一个磁盘地址
    • READ:从磁盘读取数据到主存( main memory,RAM )
    • WRITE:从主存写数据到磁盘
  • 数据在磁盘上的存储单元为块 - block ,又称为页 - page
    • 每个页面都有固定的大小,比如 512 字节。它包含一系列记录
    • 在许多(并非总是)情况下,页面的记录具有相同的大小,例如 100 字节

RAM:也叫主存,是与 CPU 直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质

  • 为什么主存不能存储所有东西
    • 价格:RAM 比磁盘贵得多
    • 主存不稳定( volitile ):即一旦断电所存储的数据将随之丢失。要求:每次程序执行完毕,数据能被存储。

存储层级:

  • 当前使用的数据存在主存( RAM )
  • 主要的数据存储放在磁盘上面(二级存储)
  • 用于归档旧版本数据的磁带 - Tape(三级存储)
    image
    image
  • 数据和成本减少的同时,存储容量增加

磁盘的组成

  • 一个 block 包含多个扇区( sector )
    image

文件组织

  • 数据库存储为文件 file 的集合,每个文件都是一个记录序列,一个记录包含着若干个字段 - fields(属性值)
    • 一个文件相当于一个表,即 relation 实例
    • 一个记录相当于表格中的一行
    • 一个表格中的记录大小是固定的
  • 如何组织记录存放在文件里面?
    • 固定大小记录
    • 可变大小记录
固定长度记录

image

  • 一般方法
    • 存储记录 i 从第 \(k × ( i - 1 )\) 个字节开始,于 $ k × i - 1$ 处结束,记录大小为 k
    • 同个文件的记录可能跨 block 存储(单个 block 不够)
  • 删除记录 i 时应如何操作?
    • 方法1:移位记录,即将记录 i + 1,......,n 移动到 i,......,n-1
    • 方法2:将记录 n 移动到 i
    • 方法3:利用一个 free list 回收这些被释放出来的空间
Free list

每个记录增加一个指针,在文件中增设一个文件首部,记录文件中的有关信息,其中有一个指针指向第一个被删除记录的位置,所有被删除结点用指针链接,构成空闲记录链表
image

可变长度记录
  • 在数据库系统中,可变长度以多种方式出现
    • 文件存储了多种不同的记录类型记录
    • 文件中允许的记录类型的字段是变长的
    • 允许记录中某个字段可以出现重复,如数组或多值集合
  • 简单(但不好)的解决方案:字节字符串记号表示记录结尾
    • 将(⊥)控制字符附加到每个记录的末尾
    • 删除困难(释放的空间碎片化)
    • 插入困难(移动记录很困难)
方法一:符号方法

预先分配最大可能长度,插入记录时用符号 ⊥ 填充未用到的部分
image

方法二:指针方法

对于某些具有重复属性的记录类型很有用
文件中的两种块:

  • 锚定块:包含链的第一条记录
  • 溢出块:包含溢出字段
    image
文件中记录的组织方式
  • 无序存放:有空间就可以放
  • 顺序存放:按某个搜索键的值的顺序存放
  • 哈希存放:根据每个记录的搜索键计算哈希值,结果指定记录应存放在哪个块中

这里的“搜索键”与关系模型中的 key 不是一个概念,这里的搜索键是指存储时,被制定用来参考,以排放记录的属性
譬如学生表,我们可以用学号作为搜索键进行排放,也可以用名字,如果用名字的话可能会有重名,此时该重名键指向的地址,则应顺序排放了所有该名字的学生

无序存放:堆排序
  • 为了实现在记录这个维度上的操作,我们需要
    • 记录每个 file 所存放的 pages
    • 记录 page 的剩余空间
    • 记录每个 page 存放了记录的位置
  • 使用页目录的堆文件
    image
    • 目录中指向每个 page 的条目中也可包含其剩余空间信息
    • 目录本身亦是 page 的集合;此处链表实现只是一种选择
顺序文件组织
  • 适用于记录总是被根据某个属性值连续访问的场景
    image
  • 擦除:用指针跳过该记录
  • 插入:找到要插入记录的位置
    • 如果有可用空间就插入那里
    • 如果没有可用空间,则将记录插入到溢出块中
  • 需要不时地重新组织文件以恢复顺序
    image
使用哈希(散列)作为文件组织
  • 假设有 10 万条员工记录,我们每页可以放 100 条记录,那么我们需要 1,000 页
  • 我们为表分配 1,2000 个 page,以便为将来的插入留出一些空间
  • 设计以工资为搜索键的哈希寻址函数为:
    • image
  • 优势:对记录进行寻址时,只需要一次哈希计算
  • 当我们插入一条新纪录的时候,我们计算工资的哈希函数并将该记录插入相应的 page
  • 如果该 page 已满,我们将创建一个溢出页面,并在那里插入新纪录
    image
  • 可以有效回答诸如“查找所有工资为 15,000 的员工”的查询
    • 计算 15000 的哈希值,然后只对对应的桶中查找,如果没有溢出桶,则只需一次读取即可回答查询
    • 如果存在溢出桶,我们必须读取所有的桶
  • 散列发不适用于范围搜索(“查找薪资在 15,000 到 16,000 之间的所有员工”),因为这些员工可能分布在不同的存储桶中

时间成本分析

  • 忽略 CPU 的时间成本( 相比磁盘读写操作时间小得多 ):
    • 以读写 page 的总次数作为衡量单位
    • 平均情况分析,它基于单个记录的插入和删除操作,伴有一些假设:
      • 堆文件
        • 搜索操作:寻找特定键值的记录,并只能有一个匹配
        • 插入操作:总是在文件末端进行插入
      • 顺序文件
        • 每次删除/插入后对记录进行整理,保证顺序
        • 搜索同上
      • 哈希文件
        • 没有溢出页面,所以我们不需要到溢出页面进行操作
          image
posted @ 2024-12-14 21:41  韦飞  阅读(43)  评论(0)    收藏  举报