寫(xiě)在開(kāi)始
1淘讥、這是一篇簡(jiǎn)單的數(shù)據(jù)庫(kù)實(shí)現(xiàn),按照自己的思路來(lái)不要求效率高不要求實(shí)用性堤如,為的是以博主這樣的小白目光來(lái)琢磨數(shù)據(jù)庫(kù)怎么去實(shí)現(xiàn)
2蒲列、博主是邊寫(xiě)代碼邊寫(xiě)博客,從最開(kāi)始的版本(可以說(shuō)根本不能叫數(shù)據(jù)庫(kù)的東西!)開(kāi)始一步步實(shí)現(xiàn)到勉強(qiáng)能看的地步
3搀罢、基于key-value和c++蝗岖,歡迎交流技術(shù),如果噴請(qǐng)輕點(diǎn)
==================================================================================================================
其實(shí)我從大學(xué)時(shí)代就不喜歡數(shù)據(jù)庫(kù)榔至,感覺(jué)很麻煩所以不想學(xué)
最近NoSQL很火抵赢,而且感覺(jué)比傳統(tǒng)的數(shù)據(jù)簡(jiǎn)單,尤其是key-value感覺(jué)像哈希表一樣的操作非常舒服洛退,所以嘗試摸索下它的原理
首先瓣俯,數(shù)據(jù)庫(kù)有哪些操作呢?打開(kāi)-關(guān)閉就不說(shuō)了兵怯,關(guān)于數(shù)據(jù)的操作大概有:寫(xiě)入(包括覆寫(xiě)和插入)彩匕、查詢、刪除媒区,其中最重要的就是查詢(因?yàn)槟銊h除和寫(xiě)入都要先找到原來(lái)的數(shù)據(jù)才能操作吧)驼仪,所以我覺(jué)得查詢的效率比較影響數(shù)據(jù)庫(kù)性能。當(dāng)然這些都是后話袜漩,先來(lái)一個(gè)不講究效率的
先實(shí)現(xiàn)一個(gè)簡(jiǎn)單的绪爸,基于內(nèi)存的數(shù)據(jù)庫(kù)(比如redis)。
什么都按最簡(jiǎn)單的來(lái)不考慮性能
那么數(shù)據(jù)庫(kù)該有的操作上面已經(jīng)說(shuō)了宙攻,先來(lái)建立一個(gè)類(lèi)吧奠货,不如叫smallsql
這個(gè)數(shù)據(jù)庫(kù)只支持10240個(gè)數(shù)據(jù),并且只支持string和int型數(shù)據(jù)
先來(lái)看看smallsql.h的定義
可能看到定義的朋友已經(jīng)開(kāi)始噴了座掘,這是什么垃圾玩意递惋,也能叫數(shù)據(jù)庫(kù),博主滾出CSDN之內(nèi)的了
哈哈溢陪,不要著急嘛萍虽。前面說(shuō)了這個(gè)文章是慢慢來(lái)逐步實(shí)現(xiàn)從最簡(jiǎn)單的開(kāi)始到面前能看的樣子
如果一來(lái)就是完整版,那不如找一個(gè)開(kāi)源數(shù)據(jù)庫(kù)大家一起分析代碼來(lái)的爽快
這是打開(kāi)和關(guān)閉數(shù)據(jù)庫(kù)的函數(shù)
bool open(const std::string& sqlPath);
void close();
這是對(duì)數(shù)據(jù)庫(kù)兩種類(lèi)型的讀寫(xiě)(不同類(lèi)型居然用兩個(gè)不同的接口來(lái)操作形真,從來(lái)沒(méi)看到什么數(shù)據(jù)庫(kù)是這樣的杉编,我們下篇文章來(lái)解決)
std::string getStr(const std::string& key);
void setStr(const std::string& key, const std::string& value);
int getInt(const std::string& key);
void setInt(const std::string key, int value);
這是數(shù)據(jù)庫(kù)的數(shù)據(jù)項(xiàng)(union被博主吃了嗎?)
struct SqlData
{
std::string key;
std::string value_str;
int value_int;
};
好大概是這樣了,來(lái)看看具體實(shí)現(xiàn)的源碼
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;
}
int index = 0;
while (!feof(fp))
{
int key_len = 0;
fread_s(&key_len, 1, 1, 1, fp);
if (key_len == 0)
{
continue;
}
char* key = new char[key_len + 1];
fread_s(key, key_len, key_len, 1, fp);
key[key_len] = 0;
m_datas[index].key = std::string(key);
delete[] key;
int value_len = 0;
fread_s(&value_len, 1, 1, 1, fp);
if (value_len != 0)
{
char* value_str = new char[value_len + 1];
fread_s(value_str, value_len, value_len, 1, fp);
value_str[value_len] = 0;
m_datas[index].value_str = std::string(value_str);
delete[] value_str;
}
int value_int = 0;
fread_s(&value_int, 4, 4, 1, fp);
m_datas[index].value_int = value_int;
index++;
}
fclose(fp);
return true;
}
這個(gè)函數(shù)負(fù)責(zé)打開(kāi)數(shù)據(jù)庫(kù)邓馒,如果不是一個(gè)新的數(shù)據(jù)庫(kù)(就是文件不存在)則負(fù)責(zé)讀取數(shù)據(jù)到內(nèi)存中嘶朱,比較簡(jiǎn)單
close和這個(gè)函數(shù)基本一樣,無(wú)非就是在關(guān)閉的時(shí)候得按照格式把數(shù)據(jù)庫(kù)存到文件里面绒净,就不貼代碼了
接下來(lái)是getStr和setStr(int操作是一樣的见咒,就不單獨(dú)說(shuō)了)
std::string smallsql::getStr(const std::string& key)
{
for (int i = 0; i < smallsql::Max_Data_Count; ++i)
{
if (m_datas[i].key == key)
{
return m_datas[i].value_str;
}
}
return std::string();
}
void smallsql::setStr(const std::string& key, const std::string& value)
{
for (int i = 0; i < smallsql::Max_Data_Count; ++i)
{
if (m_datas[i].key == key)
{
m_datas[i].value_str = key;
return;
}
else if (m_datas[i].key.empty())
{
m_datas[i].key = key;
m_datas[i].value_str = value;
m_datas[i].value_int = 0;
return;
}
}
}
可以看出,函數(shù)使用了及其暴力的方法挂疆,遍歷所有數(shù)據(jù)來(lái)實(shí)現(xiàn)數(shù)據(jù)的查找,而且存儲(chǔ)的時(shí)候也會(huì)查找
單獨(dú)說(shuō)的一點(diǎn)下翎,setStr中因?yàn)檫@個(gè)數(shù)據(jù)庫(kù)沒(méi)有刪除操作(數(shù)據(jù)段都是連續(xù)的缤言,不會(huì)出現(xiàn)中間有空),所有當(dāng)讀到第一個(gè)key是空的時(shí)候就可以存入了
接下來(lái)試試數(shù)據(jù)庫(kù)的存儲(chǔ)
可以看到视事,1W個(gè)數(shù)據(jù)的讀寫(xiě)胆萧,分別都要花8秒左右(時(shí)間是以微秒字做單位),太慢了
做死一下俐东,看看10W個(gè)數(shù)據(jù)呢跌穗,這里就不貼圖了,負(fù)責(zé)的告訴你們也就80多秒而已虏辫,哈哈
下一篇文章中蚌吸,要解決的就是數(shù)據(jù)操作的不友好,至少不能用多個(gè)API接口操作吧砌庄,而且存儲(chǔ)方式也不行啊
寫(xiě)在后面
1羹唠、不用把這一篇文章實(shí)現(xiàn)的東西看做數(shù)據(jù)庫(kù),姑且叫做數(shù)據(jù)管理器娄昆?
2佩微、文章的目的是告訴讀者,數(shù)據(jù)庫(kù)無(wú)非就是讀取和保存數(shù)據(jù)的東西萌焰,如果不考慮效率大家也都能寫(xiě)出來(lái)嘛哈哈
3哺眯、抱著學(xué)習(xí)和娛樂(lè)的心態(tài)看這個(gè)系列吧