如何做一个国产数据库

Posted qianbo_insist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何做一个国产数据库相关的知识,希望对你有一定的参考价值。

如果做一个国产数据库一链接

承接上文,继续

1、重新定义数据结构

typedef struct sdata
{
	uint32_t index;
	char vardata[128];
}sdata;

typedef struct sdata_index
{
	uint32_t index;
	uint32_t offset;
}sdata_index;

sdata_index 是我们要读到一个内存里面去的,同时,我们会使用内存查找的方式,拿到数据的索引值,在内存里面使用二分查找算法

int binSearch(uint32_t x, sdata_index *a, int n)
{
	int low, high, mid;
	low = 0;
	high = n - 1;
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (x < a[mid].index)
			high = mid - 1;
		else if (x > a[mid].index)
			low = mid + 1;
		else
			return mid;
	}
	return -1;
}

2、写入数据

修改上一文章中的写函数,数据结构,偏移量计算正确,写入文件,写入的数据在进入函数之间一定要排序

//sdata 必须是排序后数据
//2M 的索引,一半的空间为索引号码,一半的空间为数据偏移地址
//                     1024*1024/sizeof(int) 
int  bfile_write(const char * file,/*uint32_t index_num,*/ sdata data[],int n)
{
#define INDEX_BYTES 2 * 1024 * 1024
	int index_num = INDEX_BYTES / sizeof(int)*2; //max index number is 162144
	if (n > index_num)
		return -1;
	FILE * fp = fopen(file, "wb");
	if (fp == NULL)
		return -1;
	fpos_t pos_start = 0;
	fpos_t pos_index = 8;
	fpos_t pos_data = pos_index + INDEX_BYTES;
	fpos_t position =  4 + 4 + INDEX_BYTES + sizeof(data[0].vardata) * n;
	fsetpos(fp, &position);
	fsetpos(fp, &pos_start);
	//写入总索引量
	fwrite(&index_num, sizeof(int), 1, fp);
	//写入目前索引量
	fwrite(&n, sizeof(int), 1, fp);
	//排序写入文件,已经排好了序号
	//std::sort(&data[0], &data[n], Rule());
	int offsetsum = 4+4+INDEX_BYTES;
	int len = sizeof(data[0].vardata);
	for (int i = 0; i < index_num; i++)
	{
		//wnum++;
		if (i < n)
		{
			fwrite(&data[i].index, sizeof(int), 1, fp);
			fwrite(&offsetsum, sizeof(int), 1, fp);
			offsetsum += len;
		}
		else
		{
			uint64_t flag = 0;
			fwrite(&flag, sizeof(uint64_t), 1, fp);
		}
	}
	offsetsum = 4 + 4 + INDEX_BYTES;
	fpos_t pos = offsetsum;
	for (int i = 0; i < n; i++)
	{
		fsetpos(fp,&pos);
		fwrite(&data[i].vardata, strlen(data[i].vardata), 1, fp);
		pos += sizeof(data[0].vardata);
	}
	fclose(fp);
	return 0;
}

读取数据

定义读的函数,流程为
1 、读出数据最大索引量
2 、读出数据当前记录索引量
3 、读出索引放入内存
这里并不读数据集,后面第三篇再修正读数据,放一部分数据到内存里面。

//2M的空间做索引
sdata_index* bfile_read_index(const char * file,uint32_t &num)
{
	size_t nr;
	num = 0;
	uint32_t indext;//索引总长度
	uint32_t indexn;//索引长度,内容为x个索引 indexn <= indext
	FILE * fp = fopen(file, "rb");
	if (fp == NULL)
		return NULL;
	//读取最大的index值容量
	nr = fread(&indext, sizeof(uint32_t), 1, fp);
	if (nr == 0)
	{
		fclose(fp);
		return NULL;
	}
	//读取存储的索引值
	nr = fread(&indexn, sizeof(uint32_t), 1, fp);
	if (nr == 0)
	{
		fclose(fp);
		return NULL;
	}

	num = indexn;

	//4字节索引号 4字节偏移地址
	uint8_t * index = (uint8_t*)malloc(indexn * sizeof(uint32_t)*2);
	nr = fread(index, indexn * sizeof(uint32_t) * 2, 1, fp);
	if (nr == 0)
	{
		fclose(fp);
		free(index);
		return NULL;
	}
	return (sdata_index*)index;
}

定义从数据库中读取某一个索引值到内存中

int bfile_read(const char * file,uint32_t offset, char *buffer,size_t len)
{
	FILE * fp = fopen(file, "rb");
	fpos_t pos_start = offset;
	fsetpos(fp, &pos_start);
	size_t n =fread(buffer, sizeof(char)*len, 1, fp);
	fclose(fp);
	if (n != len)
		return -1;
	return 0;
}

4、定义主函数执行

int main()
{
	sdata data[100];
	//srand(1000);
	for (int i = 0; i < 100; i++)
	{
		//模拟收集到的数据
		data[i].index = i;
		sprintf(data[i].vardata, "the data is %ld", data[i].index);
	}
	//std::sort(&data[0], &data[100], Rule());
	for (int i = 0; i < 100; i++)
	{
		cout<<data[i].index<<"-->"<<data[i].vardata << endl;
	}

	bfile_write("./test.db", data, 100);

	uint32_t num;
	sdata_index *rdata =bfile_read_index("./test.db",num);

	cout << "the index number is " << num << endl;

	cout << "now read the value of index x" << endl;
	string s;
	cin>>s;

	int v = atoi(s.c_str());
	int ret = binSearch(v, rdata, num);
	sdata_index *p = rdata;
	p += ret;
	uint32_t offset = p->offset;

	char buffer[128];
	bfile_read("./test.db", offset, buffer, 128);
	
	cout << buffer << endl;


	return 0;
}

5、执行插入数据函数结果打印

执行插入数据
查看文件已经写入
查看文件

6、数据查询

输入数据查询值,如89,意思是查询第89索引的值,
首先获取内存索引中偏移量的值offset,查询的时候使用binSearch 二分查找
获取索引中偏移量的值
最后打开文件,偏移到offset处,取出拷贝里面的值,打印出 the data is 89
输入数据查询值
一个小型的数据库就这样出来了,简陋,暂时是示例,会慢慢补充起来。等待我的第三篇吧

以上是关于如何做一个国产数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何做一个国产数据库

订阅发布系统得解耦与冗余

如何做一个国产数据库

如何做一个国产数据库系统

如何做一个国产数据库

如何做一个国产数据库 hash一致性算法