基于上一章的內(nèi)容氧急,我們需要把key替換成hash值存儲(chǔ)到b+tree中
首先要改變的就是set和get函數(shù)
template<typename T>
int smallsql::getType()
{
return typeid(T) == typeid(int) ? 0 : 1;
}
template<typename T>
void smallsql::set(const std::string& key, const T& value)
{
unsigned long iKey = HashString(key, 1);
int type = getType<T>();
SqlData<T>* pItem = static_cast<SqlData<T>*>(bplus_tree_get(m_pTree, iKey, type));
if (pItem == nullptr)
{
bplus_tree_put(m_pTree, iKey, nullptr, type);
pItem = new SqlData<T>();
pItem->value = value;
bplus_tree_put(m_pTree, iKey, pItem, type);
}
else
{
pItem->value = value;
}
}
template<typename T>
T smallsql::get(const std::string& key)
{
unsigned long iKey = HashString(key, 1);
int type = getType<T>();
SqlData<T>* pItem = static_cast<SqlData<T>*>(bplus_tree_get(m_pTree, iKey, type));
if (pItem == nullptr)
{
return T();
}
else
{
return pItem->value;
}
}
這兩個(gè)函數(shù)首先都需要用HashString函數(shù)把key的內(nèi)容轉(zhuǎn)換成unsigned long類(lèi)型的整數(shù)
然后存儲(chǔ)到bplus_tree中颗胡,這些都在上一章里介紹過(guò),需要需要看具體的實(shí)現(xiàn)附件有工程文件可以看
然后就是open和close函數(shù)吩坝,他們負(fù)責(zé)讀取和保存毒姨,也需要修改
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;
}
while (!feof(fp))
{
unsigned long key = 0;
fread_s(&key, sizeof(unsigned long), sizeof(unsigned long), 1, fp);
if (key == 0)
{
continue;
}
int type = 0;
fread_s(&type, 1, 1, 1, fp);
if (type == 0)
{
int value = 0;
fread_s(&value, sizeof(int), sizeof(int), 1, fp);
SqlData<int>* pItem = new SqlData<int>();
pItem->value = value;
bplus_tree_put(m_pTree, key, pItem, type);
}
else if (type == 1)
{
int len = 0;
fread_s(&len, 1, 1, 1, fp);
char* value = new char[len + 1];
fread_s(value, len, len, 1, fp);
value[len] = 0;
SqlData<std::string>* pItem = new SqlData<std::string>();
pItem->value = std::string(value);
delete[] value;
bplus_tree_put(m_pTree, key, pItem, type);
}
}
fclose(fp);
return true;
}
void smallsql::close()
{
FILE* fp = nullptr;
fopen_s(&fp, m_sqlPath.c_str(), "w");
if (fp == nullptr)
{
return;
}
struct bplus_leaf *leaf = (struct bplus_leaf *)m_pTree->head[0];
if (leaf != NULL)
{
while (leaf != NULL)
{
for (int j = 0; j < leaf->entries; ++j)
{
fwrite(&leaf->key[j], sizeof(unsigned long), 1, fp);
fwrite(&leaf->datatype[j], 1, 1, fp);
if (leaf->datatype[j] == 0) // int
{
SqlData<int>* pItem = static_cast<SqlData<int>*>(leaf->data[j]);
fwrite(&pItem->value, sizeof(int), 1, fp);
}
else if (leaf->datatype[j] == 1) // string
{
SqlData<std::string>* pItem = static_cast<SqlData<std::string>*>(leaf->data[j]);
int len = pItem->value.length();
fwrite(&len, 1, 1, fp);
fwrite(pItem->value.c_str(), len, 1, fp);
}
}
leaf = leaf->next;
}
}
fclose(fp);
相對(duì)于上一個(gè)版本,稍微簡(jiǎn)單了點(diǎn)
另外b+tree的代碼也需要修改(相對(duì)于上一章給出的b+tree實(shí)現(xiàn)版本https://github.com/begeekmyfriend/bplustree)
需要加入int datatype[MAX_ENTRIES];表示數(shù)據(jù)類(lèi)型钉寝,另外key的類(lèi)型從int->unsigned long弧呐,相應(yīng)的函數(shù)也需要修改一下
總體來(lái)說(shuō)大概就是加入b+tree和hash算法的實(shí)現(xiàn)代碼bplustee.h/cpp和hash.h/cpp,另外小小的修改一下set和get函數(shù),open和close函數(shù)
替換完成嵌纲,趕緊看看1W個(gè)數(shù)據(jù)的測(cè)試時(shí)間俘枫,可以看出最慢的插入只需要0.07秒,而上一個(gè)版本需要7.6秒 快了100倍
這下我們可以試試10W數(shù)據(jù)了逮走,10W數(shù)據(jù)只需要0.57秒鸠蚪,而上一個(gè)版本需要80秒,快了140倍
再來(lái)試試100W數(shù)據(jù)測(cè)試师溅,最慢需要4.1秒
到這里茅信,數(shù)據(jù)庫(kù)基本能看了,至少效率比之前好多了接下來(lái)還有不少需要優(yōu)化的地方