数据库学习笔记1 - oracle & sqlserver 数据存储结构对比

学习不是一蹴而就,而是在于日积月累 -- 献给不再年轻的自己

参考文档:oracle 9i 10 g 编程艺术,MSDN


这里只列出sqlserver  & oracle 最后两级的数据存储结构对比


首先,看一下sqlserver 的数据存储结构:


       【SQL Server 中数据存储的基本单位是页。为数据库中的数据文件(.mdf 或 .ndf)分配的磁盘空间可以从逻辑上划分成页(从 0 到 n 连续编号)。磁盘 I/O 操作在页级执行。也就是说,SQL Server 读取或写入所有数据页。

        区是八个物理上连续的页的集合,用来有效地管理页。所有页都存储在区中】【摘选自msdn】

数据库学习笔记1 - oracle & sqlserver 数据存储结构对比_第1张图片

        也就是说在sqlserver 中 数据存储的最小的单位是页,我们table 中的每一行的数据都是存储在页中的,页的大小是固定的8kb。


        在数据页上,数据行紧接着标头按顺序放置。页的末尾是行偏移表,对于页中的每一行,每个行偏移表都包含一个条目。每个条目记录对应行的第一个字节与页首的距离。行偏移表中的条目的顺序与页中行的顺序相反


oracle 的数据存储结构

        块(block)是 Oracle 中最小的空间分配单位。数据行、索引条目或临时排序结果就存储在块中。通常 Oracle 从磁盘读写的就是块。Oracle 中块的常见大小有 4 种:2 KB、4 KB、8 KB 或 16 KB(尽管在某些情况下 32 KB 也是允许的;但是操作系统可能对最大大小有限制)。

数据库学习笔记1 - oracle & sqlserver 数据存储结构对比_第2张图片



    对比分析:

     sqlserver 页

               标头(页头):页码,页类型,页的可用空间以及拥有该页的对象的分配单元ID.

                                      页类型,页的可用空间都好理解(页类型:是数据页还是索引页,或者是其他类型。可用空间,顾名思义,就是还有多少存储空间)

                                       页码知道是什么东东,但是作用不明

                                       拥有该页的对象的分配单元ID:这个不理解

               页尾偏移量:记录每行数据在数据存储区域的地址 (oracle 是存放在了块头中)

               数据存储:存储数据的

     oracle块

               首部:块类型相关信息(表块,索引块),块中发生的活动事务和过去事务的相关信息,以及块在磁盘中的地址

               表目录:行对应的表相关的信息

               行目录:块中行的描述信息。指针数组,指向块中数据部分的数据行

     问题:oracle 怎样知道块是否有空闲的存储空间呢?

               oracle 是使用表的空闲列表来管理空闲存储空间的:每一张表都会维护一个或者多个空闲列表,列表中维护了当前范围内可用数据块的一个列表。如果一个数据块达到了最大的存储量,那么就从空闲列表中移除,反之如果从一个数据块中删除了一些数据,使其满足了规定的ptcused 参数的值,那么这个块将会重新进入到空闲列表中。


     猜想:往sqlserver 中tablea插入一条记录时 sqlserver 需要遍历一下tablea 使用的页,看看有没有空闲的可以存放此条数据的空间,如果有,则存放,否则,接着找

          oracle:直接从空闲列表中取一个块然后把数据放进去

          性能谁高谁低呢?


      上面提到了oracle 中的一个参数ptcused,和其对应的还有一个参数ptcfree,这两个参数是做什么用的呢?这是oracle 和 sqlserver 关于存储的另外一个区别:

      sqlserver:页大小8kb,不加控制,如果数据允许,可以存满。假如现在已经存储了7.8kb,现在又有一条新数据 (大于1kb)或者我更新了此页中的某一条数据,更新完后此页的数据大小会大于8kb,此时sqlserver 会怎样处理呢?SQL Server 将从最大长度的列开始动态将一个或多个可变长度列移动到 ROW_OVERFLOW_DATA 分配单元中的页,也就是说不得不把一部分数据移动到另外的页上去。那在我们查询时就需要把这两个也都load 到内存中。

      以下内容摘选自 msdn

   【 行不能跨页(这个不是太明白是什么意思),但是行的部分可以移出行所在的页,因此行实际可能非常大。页的单个行中的最大数据量和开销是 8,060 字节 (8 KB)。但是,这不包括用 Text/Image 页类型存储的数据。包含 varcharnvarcharvarbinary 或 sql_variant 列的表不受此限制的约束。当表中的所有固定列和可变列的行的总大小超过限制的 8,060 字节时,SQL Server 将从最大长度的列开始动态将一个或多个可变长度列移动到 ROW_OVERFLOW_DATA 分配单元中的页。每当插入或更新操作将行的总大小增大到超过限制的 8,060 字节时,将会执行此操作。将列移动到 ROW_OVERFLOW_DATA 分配单元中的页后,将在 IN_ROW_DATA 分配单元中的原始页上维护 24 字节的指针。如果后续操作减小了行的大小,SQL Server 会动态将列移回到原始数据页】


     orale 是怎么做的呢?

     主导思想是:我先给你预留点空间,万一你要是update,你就可以用我预留的空间了,如果空间够,就不用把数据放到别的块上去了。

     怎样实现的呢?在创建表时有两个参数:ptcused,ptcfree。

            ptcfree 参数描述了为了以后添加数据预留空间占数据块中的百分比,比如这个数字是20,那么对这个块插入数据时如果数据总量占到了这个块的80%,就不允许再往这个块中插入数据了。

           那么是不是说我删除了一部分数据,让这个块的空闲空间大于了20%,比如25%了,现在允许我插入一条小数据了吧?答案是不一定,需要看ptcused 的参数值。如果ptcused 的参数值是40,那么对不起,只有空闲空间大于60%之后才允许插入数据。

     怎么设置这两个参数比较合适呢?下面给出了建议

          高 PCTFREE,低 PCTUSED:如果你插入了将要更新的大量数据,而且这些更新会频繁地增加行的大小,此时就适合采用这种设置。这种设置在插入后会在块上预留大量的空间(高PCTFREE),并使得将块放回到 freelist 之前必须几乎为空(低 PCTUSED)。
         低 PCTFREE,高 PCTUSED:如果你只想对表完成 INSERT 或 DELETE,或者如果你确实要完成 UPDATE,但 UPDATE 只是缩小行的大小,此时这种设置就很适合





你可能感兴趣的:(database)