数据库系统实现实验报告1
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
四、 实验内容:
生成一个具有 10,000,000 个记录的文本文件, 其中每个记录由 100 个字节组 成。 实验只考虑记录的一个属性 A, 假定 A 为整数类型。 记录在 block 上封装时, 采用 non-spanned 方式,即块上小于一个记录的空间不使用。Block 的大小可在 自己的操作系统上查看,xp 一般为 4096 bytes。在内存分配 50M 字节的空间用 于外部 merge-sort。要求设计和实现程序完成下列功能: 1.生成文本文件,其中属性 A 的值随机产生。 2.按照 ppt 中的方法对文本文件中的记录,按照属性 A 进行排序,其中在第二 阶段的排序中每个子列表使用一个 block 大小的缓冲区缓冲数据。 3.按照教材 cylinder-based buffers(825280 bytes)的方法,修改第二阶段的算法。 4. 比较两种方法的时间性能, 如果有更大的内存空间, 算法性能还能提高多少?
数据库系统实现实验报告
一、实验名称:
Two Phase, Multiway Merge-Sort
二、实验环境:
Linux 操作系统标准 c89、c99 都可运行
三、 实验目的:
通过 merge-sort 算法的实现,掌握外存算法所基于的 I/O 模型与内存算法基 于的 RAM 模型的区别;理解不同的磁盘访问优化方法是如何提高数据访问性能 的。
五、 实验分析:
一个具有 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 个排好序的子文件进行归并排序,完成排序。
20 的,平均次数为1 2 × ������������������2 × n ≈ 3 × n(n=1000000000)但是它的 io 次数太多
������ 20
为 250020 次,即增加了程序中断开销,又增加了磁盘读取和写入的开销。 第二阶段的解决办法,减少递归的次数在数据量小于 16 时用插入排序。 第三阶段用题目要求的 cylinder-based buffers(8255280 bytes)的方法
clock_t a,b,c,d; int step1(const char*, struct btr *);//生成一个 10,000,000 个随机记录的文 件 struct pstr step2(const char*, struct btr *);//将上面的文件分成 20 个小文件 并排序 void step3(struct pstr,struct btr *);//用归并算法将上面的 20 个小文件排好续 重新放入源文件 startT=time(NULL); a=clock(); char * str="f0.txt"; //原始文件的目录 struct btr *tr; tr = (struct btr *)malloc(LS); step1(str,tr); sdT=time(NULL); b=clock(); printf("第一阶段的运行时间为%f\n",difftime( sdT, startT)); printf("%f\n",(double)(b-a)/1000); struct pstr ps= step2(str,tr); sfT=time(NULL); c=clock(); printf("第二阶段的运行时间为%f\n",difftime( sfT, sdT)); printf("%f\n",(double)(c-b)/1000); step3(ps,tr); endT=time(NULL); d=clock(); printf("%f\n",(double)(d-c)/1000); printf("第三阶段的运行时间为%f\n",difftime( endT, sfT)); printf("总运行时间为%f\n",difftime( endT, startT)); free(tr); return 0; } int step1(const char*str,struct btr *tr) { int f0; srand((unsigned)time(NULL)); f0 = open(str,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR); int i=0,j=0,m=L; while(j<D) { i=0; while(i<m) { (tr+i)->record[A]=rand();
结束
基于堆排序的归并算法:
开始
判断子文件个 数 dr>0
N
Y tr[ti]=fi[1].tf[fi[1].lesk]; ti++;
结束
ti==L
write(fg,tr,LS);ti=0 ;
fi[1].lesk==fi[1].nr Y fi[1].nr=(read(fi[1].flg,fi[1].tf,SB))/S;
图4
图5
2.结果分析
从图上可以看出 第一阶段生成一个 10000000 个记录的文件在 13 秒左右, 第 二 阶 段 生 成 20 个 小 文 件 并 排 序 在 37 秒 左 右 , 但 是 其 算 法 复 杂 度 为 o(n × ������������������2 ) ≈ ������(������)(n=512000 比较小所以可以)在考虑到 cup 的运算速度和第一 阶段生成随即数花费 的时间,第二阶段的时间应该和第一阶段的时间差不多。 第三阶段的时间为 80 秒左右,但是其算法复杂度按理来说是是三个阶段中最少
3.改进后的结果(cylinder-based buffers(825280 bytes)的方法)
考虑到一个记录 100 个字节所以去每个子列表的缓冲区为 825200bytes
图6
图7
九、实验总结
改进后的算法明显要好于第一次运行的结果。第三阶段表现最明显, Io 次数减少后时间减少了 60 秒。 如果每个子列表的缓冲区为 cylinder 的整数倍或略小于他的整数倍的话效果 都会非常的好,如果有更大的内存空间它将与第二阶段的时间一样甚至还要少。
十、实验代码
/* ============================================================================ Name : dbt.c Author : sunbo Version : Copyright : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */ #include<stdio.h> #include<stdlib.h> #include<time.h> #include<malloc.h> #include<unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define R 10000000//总记录数 #define L 512000 //内存最大记录数 #define S 100 //单个记录的长度 #define D 20 //R/L+1 #define A 0 //记录中属性 A 的位置 #define B 82252 //一个子文件的内存中的记录数 #define SB 8225200 //S*B #define LS 51200000 //L*S //表示一个记录 struct btr{ int record[25]; }; //表示子文件的路径 struct pstr{ char pt[D][30]; }; int main() { time_t startT,sdT,sfT, endT;
//printf("%d\n",(tr+i)->record[A]); i++; } write(f0,tr,i*sizeof(struct btr)); j++; if((j==(D-1))) m= R-(D-1)*L; } close(f0); return 0; } //将上面的文件分成 20 个小文件并排序 struct pstr step2(const char*str, struct btr *tr) { //快速排序 void kuip(struct btr *,int,int); //int cmp(struct btr* a, struct btr* b) //{ // return (a->record[A]-b->record[A]); //} struct pstr nps; int f0 = open(str,O_RDONLY); int nr,h=0; while((nr=read(f0,tr,LS))>0) { //qsort(tr,L,S,cmp); kuip(tr,0,nr/S-1); sprintf(nps.pt[h],"%s%d","file",h); // printf("%s\n",nps.pt[h]); int fi=open(nps.pt[h],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR); write(fi,tr,nr); close(fi); h++; } close(f0); return nps; } //快速排序 void kuip(struct btr* tr,int low1,int high1) { if(high1-low1>15){ int l1=tr[low1].record[A]-tr[high1].record[A]; int l2=tr[low1].record[A]-tr[(low1+high1)/2].record[A];
装入内存是否成功 功 Y 文件 fi 偏移量置零
N
关闭文件 fi;dr- -
进行堆排序下调算法
八、 实验截图及分析: 1.在第二阶段的排序中每个子列表使用一个 block 大小的缓冲区缓冲 数据
总体运行结果图
图1
生成 20 个小文件的图
图2
第 19 个小文件的结果
图3
文件 f0.txt 在排序前后的结果 (看其中的修改时间)
七、 实验流程图:
Step2:
开始
(nr=read(f0,tr,LS)) >0
N
Y 快速排序 关闭文件 f0
创建新文件 fi
结束
写入新文件拍好的数据
关闭文件
Step3: 开始
i<=20
N
Y 打开 i 文件
打开目标文件
进行基于堆排序的归并算法 读取 BS 个字节 删除 20 个小文 件 进行堆排序上调算法 关闭文件 f1
六、 实验步骤:
1. 生成一个具有 10,000,000 个记录的文本文件 f0.txt,其中每个记录由 100 个字 节组成,其中有一个整数类型属性 A。程序生成一个 int 型随机整数作为每条Leabharlann Baidu 录的属性 A。记录写入 f0.txt 文件中。
2. 根据实验分析,将 f0.txt 文件分为 20 个子文件,并且按照文件中每个记录的 属性对各个子文件进行内部排序(使用快速排序加快时间) ,最终形成 20 个有序 的子文件 3. 对 20 个有序的子文件进行归并排序 (在比较 20 个数大小的时候使用堆排序算 法) ,最终形成一个有序的结果文件 f0.txt,同时删除 20 个中间生成的小文件。