自己实现基于key-value的NoSQL数据库(二)—— 改进存储方式和查询修改函数

前端之家收集整理的这篇文章主要介绍了自己实现基于key-value的NoSQL数据库(二)—— 改进存储方式和查询修改函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

上一篇文章实现的数据库很不方便

一方面基于不同的数据,需要不同的函数用于存取

另一方面数据存储基于数组,大小一开始的固定的,显然不行

这一章来尝试改一改


我们希望这个数据库是动态大小的,能存多少都行

那么一提到这个,第一个想到的应该就是链表了

先来整体看看改动后的smallsql.h



可以看到数据采用链表来存储,接口也改为固定的一对get/set了,其余不变
依然来先看看open函数
bool smallsql::open(const std::string& sqlPath)
{
	FILE* fp = nullptr;
	m_sqlPath = sqlPath;

	fopen_s(&fp,sqlPath.c_str(),"r");
	if (fp == nullptr)
	{
		return true;
	}

	sqlDataList* pHead = m_pDatas;
	sqlDataList* pPre = nullptr;

	while (!feof(fp))
	{
		int type = 0;
		fread_s(&type,1,fp);

		int key_len = 0;
		fread_s(&key_len,fp);

		if (key_len == 0)
		{
			continue;
		}

		m_pDatas = new sqlDataList;
		m_pDatas->pNext = nullptr;
		m_pDatas->type = type;

		if (pPre != nullptr)
		{
			pPre->pNext = m_pDatas;
		}

		char* key = new char[key_len + 1];
		fread_s(key,key_len,fp);
		key[key_len] = 0;
		m_pDatas->key = std::string(key);

		if (type == 0)
		{
			sqlData<int>* pItem = new sqlData<int>();
			fread_s(&pItem->value,4,fp);
			m_pDatas->pValue = pItem;
		}
		else
		{
			sqlData<std::string>* pItem = new sqlData<std::string>();
			int value_len = 0;
			fread_s(&value_len,fp);
			char* value_str = new char[value_len + 1];
			fread_s(value_str,value_len,fp);
			value_str[value_len] = 0;
			pItem->value = std::string(value_str);
			delete[] value_str;
			m_pDatas->pValue = pItem;
		}

		delete[] key;

		if (pHead == nullptr)
		{
			pHead = m_pDatas;
		}

		pPre = m_pDatas;
	}

	m_pDatas = pHead;

	fclose(fp);

	return true;
}

和上一章想比,就是改变了数据的读取而已


这是改写后的get函数

template<typename T>
T smallsql::get(const std::string& key)
{
	sqlDataList* pData = m_pDatas;

	while (pData != nullptr)
	{
		if (pData->key == key)
		{
			int type = typeid(T) == typeid(int) ? 0 : 1;

			if (type == pData->type)
			{
				sqlData<T>* pItem = static_cast<sqlData<T>*>(pData->pValue);
				return pItem->value;
			}
			else
			{
				return T();
			}
		}

		pData = pData->pNext;
	}

	return T();
}


改写后的set函数
template<typename T>
void smallsql::set(const std::string& key,const T& value)
{
	sqlDataList* pHead = m_pDatas;
	sqlDataList* pPre = nullptr;

	while (m_pDatas != nullptr)
	{
		if (m_pDatas->key == key)
		{
			delete m_pDatas->pValue;
			sqlData<T>* pItem = new sqlData<T>();
			pItem->value = value;
			m_pDatas->pValue = pItem;

			if (pHead != nullptr)
			{
				m_pDatas = pHead;
			}

			return;
		}
		else
		{
			pPre = m_pDatas;
			m_pDatas = m_pDatas->pNext;
		}
	}

	sqlData<T>* pItem = new sqlData<T>();
	pItem->value = value;

	m_pDatas = new sqlDataList;
	m_pDatas->key = key;
	m_pDatas->pValue = pItem;

	if (typeid(T) == typeid(int))
	{
		m_pDatas->type = 0;
	}
	else
	{
		m_pDatas->type = 1;
	}

	m_pDatas->pNext = nullptr;

	if (pPre != nullptr)
	{
		pPre->pNext = m_pDatas;
	}

	if (pHead != nullptr)
	{
		m_pDatas = pHead;
	}
}

新的get和set用模板来当做数据项保存内容,实现一个接口存储,比上一章要好了不少了

另外这里的typeid其余可以考虑用模板特化来消除掉


总体来说,这一版改动了数据的存储格式和查询修改的接口

这是1W个数据的时间,相比上一章没什么大的变化因为并没有优化过,10W个数据的时间任然惨不忍睹 哈哈



看来当务之急的解决效率问题了,10W个数据的操作80多秒是不能忍受的

下一章就尝试解决这个问题


附上本章代码工程,VS2013

http://pan.baidu.com/s/1sjmMp6P

原文链接:https://www.f2er.com/nosql/203876.html

猜你在找的NoSQL相关文章