顺序文件上的索引(一)

研究索引结构,我们首先来考虑最简单的一种:由一个称为数据文件的排序文件得到另一个称为索引文件的文件,而这个索引文件由键-指针对组成。在索引文件中查找键K通过指针指向数据文件中查找键为K的记录。索引可以是“稠密的”,即数据文件中每个记录在索引文件中都设有一个索引项;索引也可以是“稀疏的”,即数据文件中只有某些记录在索引文件中表示出来,通常为每个数据块在索引文件中设一个索引项。

1、顺序文件

一种最简单的索引结构要求文件按索引的属性排序,这样的文件称为顺序文件。当查找键是关系的主键时这种结构特别有用,当然对关系的其他属性也可使用这种结构。图4-2所示为一个用顺序文件表示的关系。

============================键以及几种不同的键=========================

术语“键”有几个涵义,本书在适当的上下文中使用了“键”的不同涵义。你肯定对“键”用来表示“关系的主键”十分熟悉。这样的键用SQL定义。且需要关系满足在主键属性或属性组上不存在值相同的两个元组。

在2.3.4节中我们学过“排序键”,文件的记录据此排序。现在来看“查找键”已知在该属性(组)上的值,需要通过索引查找具有相应值的元组。当“键”的涵义不清楚时,尽量使用恰当的修饰词(“主”、“排序”或“查找”)。不过请注意,在4.1.2节和4.1.3节中,很多时候这三种键是同一涵义。

=======================================================================

在这个文件中,元组按主键排序。这里假定主健是整数,我们只列出了主键字段。同时,我们还做了一个不代表典型情况的假定,即每个存储块中只可存放两个记录。例如,文件的第一个块中存放键值为10和20的两条记录。在这里和其他许多例子中,我们使用10的连续倍数来做键值,虽然实际中不会要求键值都是10的倍数或10的所有倍数都必须出现。


2、稠密索引

既然把记录排好了序,我们就可以在记录上建立稠密索引。它是这样的一系列存储块:块中只存放记录的键以及指向记录本身的指针,指针就是如3.3节讨论的那样的地址。我们说这里的索引是“稠密的”,因为数据文件中每个键在索引中都被表示出来。与此相比,将在4.3节中讨论的“稀疏”索引通常在索引中只为每个数据块存放一个键。

稠密索引文件中的索引块保持键的顺序与文件中的排序顺序一致。既然假定查找键和指针所占存储空间远小于记录本身,我们就可以认为存储索引文件比存储数据文件所需存储块要少得多。当内存容纳不下数据文件但能容纳下索引文件时,索引的优势尤为明显。这时,通过使用索引文件,我们每次查询只用一次I/O操作就能找到给定键值的记录。

例4.1 图4-3所示为一个建立在顺序文件上的稠密索引,该顺序文件的起始部分如图4-2所示。为了方便起见,还是假定文件中记录的键值是10的倍数,虽然实际中我们不能指望找到这样一个有规律的键值模式。我们还假定每个索引存储块只可存放四个键-指针对。在实际中我们会发现每个存储块能存放更多的键-指针对,甚至是好几百个。

第一个索引块存放指向前四个记录的指针,第二个索引块存放指向接下来的四个记录的指针,依此类推。出于将在4.1.6节讨论的原因,实际中我们可能不希望装满所有的索引块。

稠密索引支持按给定键值查找相应记录的查询。给定一个键值K,我们先在索引块中查找K。

当找到K后,按照K所对应的指针到数据文件中寻找相应的记录。似乎在找到K之前我们需要检索索引文件的每个存储块,或平均一半的存储块。然而,由于有下面几个因素,基于索引的查找比它看起来更为有效:

1)索引块数量通常比数据块数量少。

2)由于键被排序,我们可以使用二分查找法来查找K。若有n个索引块,我们只需查找log2n个块。

3)索引文件可能足够小,以致可以永久地存放在主存缓冲区中。要是这样的话,查找键K时就只涉及主存访问而不需执行I/O操作。

094844721.jpg


例4.2 假设一个关系有1000000个元组,大小为4096字节的存储块可存放10个这样的元组,那么这个关系所需的存储空间就要超过400MB,因为太大而可能在主存中无法存放。然而,要是关系的键字段占30字节,指针占8字节,加上块头所需空间,那么我们可以在一个小大为4096字节的存储块中存放100个键-指针对。

这样,一个稠密索引就需要10000个存储块,即40MB。我们就有可能为这样一个索引文件分配主存缓冲区,不过要看主存的使用情况和主存的大小。进一步讲,log2(10000)大约是13,因此采用二分查找法我们只需访问13~14个存储块就可以查找到给定键值。且由于二分查找法只检索所有存储块中一小部分(是这样一些存储块,它们位于1/2、1/4或3/4、1/8或3/8、5/8或7/8,等等),即使不能把整个索引文件存放到主存中,我们也可以把这些最重要的存储块放到主存中,这样,检索任何键值所需的I/O次数都远小于14。


================================索引块的定位===================================

假设存在一些定位索引块的机制,根据索引可以查找到单个元组(若是稠密索引)或数据存储块(若是稀疏索引)。许多定位索引的机制可以使用。例如。假如索引较小,我们可以将它存放到主存或磁盘的预留存储区中。假如索引较大,则如我们在4.1.4节讲述的那样,我样可以在索引上再建一级索引,并将新的索引本身存放到某个固定的地方。对这一观点进行推广。最后就产生了4.3节中的B树,在B树中我们只需要知道根索引块的位置。

================================================================================

3、稀疏索引

要是稠密索引太大,我们可以使用一种称为稀疏索引的类似结构。它节省了存储空间,但查找给定值的记录需更多的时间。如图4-4所示,稀疏索引只为每个存储块设一个键-指针对。键值是每个数据块中第一个记录的对应值。


094902937.jpg

例4.3 同例4.1一样,假定数据文件已排序,且其键值为连续的10的倍数,直至某个较大的数。我们还继续假定每个存储块可存放四个键-指针对。这样,第一个索引存储块中为前四个数据存储块的第一个键值的索引项,它们分别是10、30、50和70。按照前面假定的键值模式,第二个索引存储块中为第5~第8数据存储块的第一个键值的索引项,它们分别是90、110、130和150。图中还列出第三个索引存储块存放的键值,它们分别是假设的第九~第十二个数据存储块的第一个键值。


例4.4 稀疏索引所需的索引存储块要比稠密索引少得多,以例4.2中更接近实际的参数为例。由于有100000个数据存储块,且每个索引存储块可存放100个键-指针对,那么要是使用稀疏索引,我们就只需要1000个索引存储块。现在索引的大小只剩下4MB,这样大小的文件完全可能存到主存中。

另一方面,稠密索引不用去检索包含记录的块,就可以回答下面形式的查询:“是否存在键值为K的记录?”。键K在索引中的存在足以保证数据文件中键值为K的记录的存在。当然如果使用稀疏索引,对于同样的查询,却需要执行I/O操作去检索可能存在键值为K的记录的块。

在已有稀疏索引的情况下,要找出键值为K的记录,我们得在索引中查找键值小于或等于K的最大键值。由于索引文件已按键排序,我们可以使用二分查找法来定位这个索引项,然后根据它的指针找到相应的数据块。现在我们必须搜索这个数据块以找到键值为K的记录。当然,数据块中必须有足够的格式化信息来标明其中的记录及记录内容。只要合适,可以采用3.2节和3.4节中的任何技术。


4、多级索引

索引文件本身可能占据多个存储块,正如我们在例4.2和例4.4中看到的那样。要是这些存储块不在我们知道能找到它们的某个地方,比如指定的磁盘柱面,那么,就可能需要另一种数据结构来找到这些索引存储块。即便能定位索引存储块,并且能使用二分查找法找到所需索引项,我们仍可能需要执行多次I/O操作才能得到我们所需的记录。

通过在索引上再建索引,我们能够使第一级索引更为有效。图4-5对图4-4进行了扩展,它是

在图4-4的基础上增加二级索引得到的(和前面一样,我们假设使用10的连续倍数这一不常见的模式)。按照同样想法,我们可以在二级索引的基础上建立三级索引,等等。然而,这种做法有它的局限,与其建立多级索引,我们宁愿考虑使用在4.3节讲述的B树。

在这个例子中,一级索引是稀疏的,虽然我们也可以选择稠密索引来作为一级索引。但是,

二级和更高级的索引必须是稀疏的,因为一个索引上的稠密索引将需要和其前一级索引同样多的键-指针对,因而也就需要同样的存储空间。因此,二级稠密索引只是增加额外的结构,而不会带来任何好处。

例4.5 继续以例4.4中假设的关系来分析,假定我们在一级稀疏索引上建立二级索引。由于一级稀疏索引占据1000个存储块,且我们可以在一个存储块中存放100个键-指针对,则只需要10个存储块来存放这个二级索引。

10个存储块完全可以一直缓存在主存中。若是这样,要查找给定键值K的记录,可以先查看二级索引以找到小于或等于键值K的最大键值。根据这个最大键值对应的指针找到一级索引的某个存储块B,通过这个存储块B,我们就肯定能找到所需的记录。假若存储块B不在内存中,我们就把存储块B读进内存,这是我们所需的第一次I/O操作。在块B中查找小于或等于键值K的最大键值,要是有键值为K的记录存在,则通过块B中这一键值对应的指针就可以找到包含键值为K的记录的数据块。这个数据块需要又一次的I/O操作。这样,我们只用两次I/O操作就完成了查询。

094920191.jpg

oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html