Cstore project 的总结

        经过一段时间的努力,终于完成了Cstore的一个简单版本的编写,在这一次的项目中,测试数据来源于TPC-H,本文主要讨论的是关于如何导入数据、外排序和JOIN操作。

1、Main函数

       首先讨论的是主函数,问题很简单,如何向主函数总传入参数?首先我们知道的是main函数可以简写为mian(),但其实main函数的完整写法应当为main(int argc,char            *argv[]),其实不难猜到,int型参数argc传入          的是argv数组中的元素个数,argv数组将会向主函数中传入参数。例如:我们的应用程序命名为a.out,我们如下            运行应用程序:a.out join orders.tbl。这样我们就可以知道,argc = 2,argv[0] = join,argv[1] = orders.tbl。

2、load函数

       在这个函数中,我们先来讲一讲文件操作FILE*,这是一个文件指针。什么是文件指针呢?例如:FILE* fp = fopen("文件的相对路径", "w+")。fopen()函数需要两个参数,第一个参数是文件的相对路径,这里就不多解了。 第二个参数有几种类型:w、r、wb、rb、ab、w+、r+、wb+、rb+、ab+、at+。以下来源于维基百科fopen():

       r 以只读方式打开文件,该文件必须存在。

       r+ 以可读写方式打开文件,该文件必须存在。

       rb+ 读写打开一个二进制文件,允许读写数据,文件必须存在。

       rw+ 读写打开一个文本文件,允许读和写。

       w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。

       w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

       a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)

       a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。(原来的EOF符不保留)

       wb 只写打开或新建一个二进制文件;只允许写数据。

       wb+ 读写打开或建立一个二进制文件,允许读和写。

       ab+ 读写打开一个二进制文件,允许读或在文件末追加数据。

       at+ 打开一个叫string的文件,a表示append,就是说写入处理的时候是接着原来文件已有内容写入,不是从头写入覆盖掉,t表示打开文件的类型是文本文件,+号表示对文件既可以读也可以写。


       讲完了fopen()函数之后,我们讲讲另外一个问题,关于c语言中的正则表达式。在.tbl表中,数据是通过如下形式存储的(注意!这只是一个举例,只是一种形式):int|string|double|char|int|。我们可以使用sscanf()函数把他们读取出来。对于上面列举的那几个数据,我们做几个假设,这些数据存储在a.tbl文件中并且这个文件和我们的程序代码在同一文件夹下,int|string|double|char|int|表示一行数据,a.tbl中有若干行数据。那么我们讲这样读取这些数据:

FILE* fp = fopen("a.tbl", "w");
int a;
char b[100];
double c;
char d;
int e;
char data[1024];
fgets(data, 1024, fp);
sscanf(data, "%d|%[^|]|%lf|%c|%d",&a,b,&c,&d,&e);

这样我们就得到了我们先搞的数据,分别存储在a,b,c,d,e中。这里有一个问题,为什么string的地方不使用%s,而使用的是%[^|],如果使用%s的话,那么不会把|作为区分,会把后面的所有数据都读入b中。


3、外排序函数

       在外排序中遇到的一个很大的问题是,不知道临时文件的个数,所以对于临时文件的命名将会是一个难题,如何对临时文件进行动态的命名呢?我们找到了sprintf()函数,sprintf (filename, "temp%d%s", filecount, ".bin");

这一段代码可以这样分析,其中filecount是一个整型的变量,假设现在filecount的值为5,那么我们可以得到filename = temp5.bin。这样就解决了对临时文件命名的问题。


4、join操作

       在我看来,join操作是一个比较麻烦的问题,需要进行RLE压缩之后,才可以进行排序,这里使用的是时间复杂度最小的算法:

while (!feof(po_o) && !feof(po_c) && !feof(p_c)) {
        if (o_custkey < c_custkey) {
            while (fread (&o_orderkey, sizeof(int), 1, po_o) && fread (&o_custkey, sizeof(int), 1, po_c) && o_custkey < c_custkey) {}
        }
        if (o_custkey > c_custkey) {
            while (fread (&c_custkey, sizeof(int), 1, p_c) && o_custkey > c_custkey) {}
        }
        if (o_custkey == c_custkey) {
            fprintf (stdout, "%d\t%d\n", o_custkey, o_orderkey);
			fwrite (&o_custkey, sizeof(int), 1, pout);
            while (fread (&o_custkey, sizeof(int), 1, po_c)) {
                  fread (&o_orderkey, sizeof(int), 1, po_o);
                  if (o_custkey != c_custkey) break;
                  fprintf (stdout, "%d\t%d\n", o_custkey, o_orderkey);
			      fwrite (&o_custkey, sizeof(int), 1, pout);
            }
         } 
	}
这个问题在谷歌上很容易就可以找到,可以自行解决。这里要说明的一个地方是关于feof()这个函数的使用,说实话,如果不是迫不得已,我是不会考虑使用这个函数的,因为这个函数在读到文件尾部的时候并不结束,它会再向下多读一位。所以如果想要能够准确的控制文件的结束,可以使用fread()一类的函数,只要读到文件尾部的时候,将会返回的是0,否则返回fread读取了的文件数量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值