数据库的存储原理

在数据库管理系统中,数据的存取过程为:

  1. 应用程序通过 DML 向 DBMS 发出存取请求,如 SELECT 语句;
  2. 对命令进行语法检查,正确后检查语义和用户权限(通过数据字典 DD),并决定是否接收;
  3. 执行查询优化,将命令转换成一串单记录的存取操作序列;
  4. 执行存取操作序列;
  5. 在缓冲区中找记录,若找到转 10,否则转 6;
  6. 查看存储模式,决定从哪一个文件,用什么方式读取物理记录;
  7. 根据 6 的结果向操作系统(OS)发出读取记录的命令;
  8. OS 执行该命令,并读取记录数据;
  9. 在 OS 控制下,将读出的记录送入系统缓冲区;
  10. RDBMS 根据查询命令和 DD 的内容导出用户所要读取的记录格式;
  11. RDBMS 将数据从系统缓冲区中送入用户工作区;
  12. RDBMS 将执行状态信息(成功或失败)返回给应用程序;
  13. 应用程序对工作区中读出的数据进行相应处理。

数据库用文件的方式来存储数据。文件在逻辑上可看作是记录的序列,物理上这些记录被映射到磁盘块中。

当一条记录被删除时,可以把紧跟其后的记录移到被删记录的位置,以此类推,直到被删记录后面的每一条记录都向前做了移动。

但这种方法需要移动大量的记录,并不理想。所以可以暂时让被删除记录的空间一直空着,等待随后插入的记录使用这个空间。但仅在被删记录上做一个删除标记是不够的,因为当插入操作执行时,要找到这个可用空间比较困难,解决方法是引入额外的结构。

在文件的开始处,分配一定数量的字节作为文件头,文件头中存储有关文件的各种信息,也记录了第一条被删除的记录。再在第一条被删除记录的后面记录第二条被删除记录,这样就形成了一条链表,称为空闲链表。

文件中存储记录的常用方法有:堆文件组织,顺序文件组织,多表聚集文件组织,B+ 树文件组织和散列文件组织(后两种多用于索引记录)等。

一条记录可以放在文件中的任何地方,只要那个地方有空间存放记录。也就是说,文件中的记录是没有顺序的,是堆积来的。

顺序文件是为了高效地按某个搜索码值的顺序有序处理记录而设计的(搜索码是一个属性或属性集合,他不一定是主码甚至是超码)。为了快速地按搜索码值得顺序获取记录,通常通过指针将文件块逻辑上有序地连接起来。每个文件块的指针指向搜索码值顺序的下一个文件块(链表形式)。同时,为了减少顺序文件处理中文件块的访问数量,在物理上按搜索码值的顺序或者尽可能的接近搜索码值的顺序存储文件块。

顺序文件组织对于那些按搜索码值有序的特定查询非常有效,然而在插入和删除记录时为了维护记录的物理顺序却十分困难。改进操作:

  • 插入操作:在文件中按搜索码值定位到待插入记录的文件块。
    • 如果文件块 A 中有空闲空间,就在该文件中定位插入记录的位置,并插入新的记录;
    • 否则申请一个溢出文件块,将文件块 A 中的记录平分一半到溢出文件块中,并将待插入记录插入到文件块 A 或溢出文件块中,再调整指针,使其能按搜索码值的顺序把文件块连接起来。
  • 删除操作:在文件中按搜索码值定位待删除记录所在的文件块。在文件块 A 中定位待删除记录并实施删除(需要在文件块内向前移动删除记录之后的原有记录,使文件块内的空闲空间位于块尾)。如果删除后记录太少,
    • 可考虑将文件块 A 的记录移到文件块所连接的文件块中,并释放 A 的空间。
    • 可考虑从文件块 A 所连接的文件块中移出一部分记录到 A 中。

通常,在小型数据库管理系统中,每个关系的所有记录存储在一个单独的定长记录的文件中,这样可以充分利用操作系统所提供的文件系统功能,简化 DBMS 的设计。

然而,很多大型数据库管理系统在文件管理方面并不直接依赖操作系统,而是让操作系统分配给 DBMS 一个大的操作系统文件,DBMS 将所有关系存储在这个文件中,并且自己管理这个文件。

多表聚集文件组织是一种在每一个文件块中存储两个或多个关系的相关记录的文件结构。这种结构将多个关系的元组(行)混合在一起聚集存储,从而支持高效的连接运算。

例:

  • 当 Student 表和 Score 表根据 studentNo 进行连接运算时,DBMS 会将 Score 表中所有 studentNo 值相同的元组(行)聚集地存储在 Student 表中对应元组的附近。
  • 当读取 Student 表中的一个元组 t(行),包含元组 t 的整个文件块已经从磁盘中读取到主存储器中。由于 Score 关系中所有与元组 t 具有相同 studentNo 值得元组已聚集在元组 t 附近,所以已读入主存中包含元组 t 的文件块中也将包含 Score 表中与元组 t 相匹配的元组。

数据库基础知识:SQL Server存储过程入门必知

SQL语句需要先编译然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。

CREATE PROCEDURE 过程名([[IN|OUT|INOUT] 参数名 数据类型[,[IN|OUT|INOUT] 参数名 数据类型…]]) [特性 …] 过程体

MySQL默认以\”;\”为分隔符,如果没有声明分割符,则编译器会把存储过程当成SQL语句进行处理,因此编译过程会报错,所以要事先用“DELIMITER //”声明当前段分隔符,让编译器把两个\”//\”之间的内容当做存储过程的代码,不会执行这些代码;“DELIMITER ;”的意为把分隔符还原。

调用方式:call 存储过程名称 – 删除方式:drop procedure 存储过程名

存储过程中使用用户变量

储存过程之间传递用户变量 create procedure cd21() set @name = \’join\’; create procedure cd22() select @name; call cd22(); call cd21(); call cd22();

注意:滥用用户变量会导致程序难以理解及管理

in:in类型的参数,存储过程中的代码对其进行的修改并不会影响该变量实际的值,属于有去无回 – out:out类型参数,用于输出值,会忽略传入的值。在子程序内部可以对其进行修改。 – inout:该类型数据综合了上述两种类型的特点,可以传入也可以被修改

FOUND_ROWS():上次查询的结果的行数 – row_count():上次增删改影响的行数 – select last_insert_id():获取上一次自动增长的id

执行速度快 – 允许模块化程序设计 – 提高系统的安全性 – 减少网络流量

账户【id,用户名,密码,钱数】,日志【id,描述】两个表

写一个存储过程输入参数3个,一个输出参数,用户名,密码,初始金额,用于办卡,生成一条用户名系,并将此记录到日志表中。【1,id:1办卡成功】 – 写一个存储过程参数一个uname,输出参数一个varchar类型,根据该用户的钱数判断,是土豪或者不是【>10000是土豪】,将结果以输出参数的方式传出

数据库的存储结构

数据库的存储结构数据库的存储结构是怎样的?

记录是按照行存储的,但是数据库的读取不是以行为单位,否则一次读取只能处理一行,效率很低。因此数据库,无论是读一行,还是读取多行,都是将这些行所在的页进行加载。数据管理存储空间的基本单位是页(Page)

快速回顾一遍数据库存储结构:一页可以存储多个行记录(Row) ,先是表空间(Tablespace),表空间包含段(segement),还存在区(Extent),其关系如下图所示:

  • 段(Segment)段里面有多个区,区在文件系统是一个连续的分片空间,不过在段中不要求区与区之间是分配单位,不同类型的数据库对象以不同的段形式存在。 当我们创建数据表,索引的时候,就会创建对应的段,比如建表的时候,会自动创建表段,创建表索引的时候,会创建一个索引段。
  • 区(Extent) 是一个比页高一个级别的存储结构,一个区一般有64个里连续的页,InnoDB 页的默认大小是 16K, 索引一个区的大小是 64*16 = 1MB
  • 表空间(Tablespace) 是一个逻辑容器,表空间存储的对象是段,在一个表空间中可以有多个段,一个段只能属于一个表空间,数据库可以有多个表空间,表空间从管理上划分为系统表空间、用户表空间、撤销表空间、临时表空间。

oracle 中使用代表

数据库 IO 最小单位是页,与数据库相关的内容会存在页结构中,数据页包括7个部分,分别是文件头(File Header),页头(Page Header),最大最小记录(Inflimum+siprenum)、用户记录(User Records)、空闲空间(Free Space),页目录(Page Directory)和文件尾(File Tailer)。

页的存储结构如下:

页中各项内容:

页主要分成3部分: 头尾节点部分。数据记录部分,索引部分。

数据页有两个字段,分别是文件头FIL_PAGE_PREV 和文件尾 FIL_PAGE_NEXT, 主要作用是指针,分别指向上一个数据和下一个数据,连接起来相当于一个双向链表。

第二部分是记录部分,最大最小记录和用户记录部分占了页结构的主要空间。当新记录插入的时候,会从空想空间分配用于存储新记录。

第三部分是索引部分, 这部分是页目录,起到了记录索引的作用。

如何创建一个页记录?

  1. 将索引的记录分成几组,这些记录包括最小记录和最大记录,但是不包括已删除记录。
  2. 第1组,也就是最小记录所在的分组只有一个记录; 最后一组,就是最大记录所在的分组,会有1-8个记录,其余的组数据在4-8条。
  3. 在每个组最后一条记录的头信息中会存储该组一共有多少条,作为 n_owned 字段。
  4. 页目录用来存储每组最后一条记录的地址偏移量,这些地址偏移量会按照先后顺序存储起来,每组的地址偏移量称为 slot ,每个槽相当于指针指向了不同组的最后一个记录。

总结一下

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。