B -树索引的建立
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据库系统实现
实验报告
实验名称: B -树索引的建立
一、实验内容
使用B-树对数据库进行索引。按照学生ID建立起B树索引。实验需要建立两个文本文件:数据文件datafile.txt和命令文件command.txt。数据文件包含了所有需要建立检索的学生信息,文本中的每一行包含一个学生的信息。每一行将由6个空格分隔的字符段组成:ID (9位),姓(最多15个字符),名(最多
15个字符),年级(1位),专业(最多4个字符),以及邮箱地址(最多20个字符)。
二、实验分析:
三、步骤分析及流程图
步骤分析:一个具有10,000,000个记录的文本文件共计10,000,000*100B=1000MB,而内存只有50MB,50MB/4KB=50*1024 KB/4KB=12800块,每块可以存放4*1024B/100B=40个记录,每块剩余96KB,内存一共可以存放12800*40=512000个记录,一共有10,000,000个记录。
所以要进行10,000,000/512000=19.53次,即20次排序,每次排序的记录数为10,000,000/20=500,000个记录。
因此此次实验需要将文本文件分成20个子文件。分别对子文件分别进行内部排序。最后对20个排好序的子文件进行归并排序,完成排序。
故将其分为三个阶段
1.生成一个具有10,000,000个记录的文本文件data.txt,其中每个记
录由100个字节组成,其中只有一个整数类型属性A,剩余字节用0
填充。程序生成一个4个字节之内随机整数作为每条记录的属性,
剩余字节用0填充。记录写入data.txt文件中。
2.根据实验分析,将data.txt文件分为20个子文件,并且按照文件
中每个记录的属性对各个子文件进行内部排序,最终形成20个有序
的子文件data1.txt,data2,txt,…data20.txt。
3.对20个有序的子文件进行归并排序,最终形成一个有序的结果文件
result.txt。
流程图:
阶段一流程图见图1.1
图1.1 随机生成10,000,000个记录的文件流程图阶段二流程图见图1.2
图1.2 分离出20个内部有序的子文件流程图
阶段三流程图见图1.3
图1.3 将20个有序的子文件进行归并排序的流程图
四、算法优化
开始在阶段二,我们小组是利用自己写在类JL里的函数sort,采用选择序方法,运行后发现因为数据量大,产生速度特别慢。后来尝试用了快速排序,但是上网查了之后,发现调用java里面原有的排序函数速度更快。
五、实验中遇到的问题及解决
问题:函数produceResult()中我在写路径的时候,不小心多写了”/.txt”
而这个是通过编译的,却导致阶段三长时间运行不出来,开始还以为算法出了问题。
解决:将路径正确书写。
六、实验结果及分析
1.生成一个具有10,000,000个记录的文本文件xyj.txt。
2.将data.txt文件分为20个子文件,并且按照文件中每个记录的属性对
各个子文件进行内部排序,最终形成20个有序的子文件data0.txt,data1.txt,…data19.txt。这个阶段所用时间为46秒。
3.对20个有序的子文件进行归并排序,最终形成一个有序的结果文件
result.txt。所用时间为40秒。
4.按照教材cylinder-based buffers(1M bytes)的方法,修改第二阶段的
算法所得结果:
而为改进前的结果为
可见,第二阶段排序所用时间为46秒,比上次时间的7分46秒明显缩短,跟我们预期的结果一致。
七、实验小结
这次实验是我第一次和他人合作一起做一个程序,感觉沟通交流还是非常重要的,还有要花时间去理解他人的想法,这些都让我收获良多。至于阶段三的归并排序,因为此前已经在数据结构中用C++实现过,即使不太擅长java语言,还是能较快的做出来。通过这次实验,我了解了数据库中的大量数据的读取并没有想象中那么简单,在数据量多的时候,一个好的算法的作用是很大的,也更好的理解了归并排序在大文件排序中的作用和性能。
代码部分
BTree.h文件
#include
#include
#include
#include
#include
using namespace std;
#define m 3 //B树的阶即一个节点有3个键值,4个指针
//学生类
class Student
{
public:
string StudentId; //学生ID (9位)
string StudentFirstName; //姓(最多15个字符)
string StudentLastName; //名(最多15个字符)
int grade; //年级
(1位)
string Major; //专业(最多4个字符)
string email; //邮箱地址
(最多20个字符)
int Id; //int型
的学生id,便于节点处理
Student(){} //空的
构造函数
Student(string id, string firstn, string lastn, int grade, string major, string mail); //构造函数
};
//node类即B树中的一个节点
class Node
{
public:
int num; //一个节点对应的键值个数
int key[m + 1]; //一个节点键值,之所以+1,便于后面节点分裂
Node * ptr[m + 1]; //一个节点的指针数
Node * parent; //指向父节点的指针
Node(); //默认构造函数让所有值为空
Node(int number, int k[]); //构造函数初始化一个节点,它的键值为数组k的值,键值个数为number个
bool isLeafNode(Node * node);//判断是否为叶子节点
};
//Result结构体用在查询函数上
struct Result
{
Node * nptr; //对应数据键值所在节点的指针
int position; //对应数据键值在节点中的位置,从0开始算
bool tag; //该键值是否在节点中
};
//B树类
class BTree
{
public:
Result search( int id); //查找学生id(键值)
void insert1(int id); //添加数据键值函数1,即情况1:叶节点未满,插入数据后不用分裂节点
void insert2(Result a, int id); //添加数据键值函数2,即情况2:叶节点满,插入数据后需要分裂叶节点,但是内层节点还有空间不需要分裂