自己实现基于key-value的NoSQL数据库(四)—— 新版本的数据库

前端之家收集整理的这篇文章主要介绍了自己实现基于key-value的NoSQL数据库(四)—— 新版本的数据库前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

基于上一章的内容,我们需要把key替换成hash值存储到b+tree中

首先要改变的就是set和get函数

  1. template<typename T>
  2. int smallsql::getType()
  3. {
  4. return typeid(T) == typeid(int) ? 0 : 1;
  5. }
  6.  
  7. template<typename T>
  8. void smallsql::set(const std::string& key,const T& value)
  9. {
  10. unsigned long iKey = HashString(key,1);
  11. int type = getType<T>();
  12. sqlData<T>* pItem = static_cast<sqlData<T>*>(bplus_tree_get(m_pTree,iKey,type));
  13.  
  14. if (pItem == nullptr)
  15. {
  16. bplus_tree_put(m_pTree,nullptr,type);
  17.  
  18. pItem = new sqlData<T>();
  19. pItem->value = value;
  20. bplus_tree_put(m_pTree,pItem,type);
  21. }
  22. else
  23. {
  24. pItem->value = value;
  25. }
  26. }
  27.  
  28. template<typename T>
  29. T smallsql::get(const std::string& key)
  30. {
  31. unsigned long iKey = HashString(key,type));
  32.  
  33. if (pItem == nullptr)
  34. {
  35. return T();
  36. }
  37. else
  38. {
  39. return pItem->value;
  40. }
  41. }

这两个函数首先都需要用HashString函数把key的内容转换成unsigned long类型的整数

然后存储到bplus_tree中,这些都在上一章里介绍过,需要需要看具体的实现附件有工程文件可以看


然后就是open和close函数,他们负责读取和保存,也需要修改

  1. bool smallsql::open(const std::string& sqlPath)
  2. {
  3. FILE* fp = nullptr;
  4. m_sqlPath = sqlPath;
  5.  
  6. fopen_s(&fp,sqlPath.c_str(),"r");
  7. if (fp == nullptr)
  8. {
  9. return true;
  10. }
  11.  
  12. while (!feof(fp))
  13. {
  14. unsigned long key = 0;
  15. fread_s(&key,sizeof(unsigned long),1,fp);
  16.  
  17. if (key == 0)
  18. {
  19. continue;
  20. }
  21.  
  22. int type = 0;
  23. fread_s(&type,fp);
  24.  
  25. if (type == 0)
  26. {
  27. int value = 0;
  28. fread_s(&value,sizeof(int),fp);
  29.  
  30. sqlData<int>* pItem = new sqlData<int>();
  31. pItem->value = value;
  32.  
  33. bplus_tree_put(m_pTree,key,type);
  34. }
  35. else if (type == 1)
  36. {
  37. int len = 0;
  38. fread_s(&len,fp);
  39. char* value = new char[len + 1];
  40. fread_s(value,len,fp);
  41. value[len] = 0;
  42.  
  43. sqlData<std::string>* pItem = new sqlData<std::string>();
  44. pItem->value = std::string(value);
  45. delete[] value;
  46.  
  47. bplus_tree_put(m_pTree,type);
  48. }
  49. }
  50.  
  51. fclose(fp);
  52.  
  53. return true;
  54. }
  55.  
  56. void smallsql::close()
  57. {
  58. FILE* fp = nullptr;
  59.  
  60. fopen_s(&fp,m_sqlPath.c_str(),"w");
  61. if (fp == nullptr)
  62. {
  63. return;
  64. }
  65.  
  66. struct bplus_leaf *leaf = (struct bplus_leaf *)m_pTree->head[0];
  67. if (leaf != NULL)
  68. {
  69. while (leaf != NULL)
  70. {
  71. for (int j = 0; j < leaf->entries; ++j)
  72. {
  73. fwrite(&leaf->key[j],fp);
  74. fwrite(&leaf->datatype[j],fp);
  75. if (leaf->datatype[j] == 0) // int
  76. {
  77. sqlData<int>* pItem = static_cast<sqlData<int>*>(leaf->data[j]);
  78. fwrite(&pItem->value,fp);
  79. }
  80. else if (leaf->datatype[j] == 1) // string
  81. {
  82. sqlData<std::string>* pItem = static_cast<sqlData<std::string>*>(leaf->data[j]);
  83. int len = pItem->value.length();
  84. fwrite(&len,fp);
  85. fwrite(pItem->value.c_str(),fp);
  86. }
  87. }
  88. leaf = leaf->next;
  89. }
  90. }
  91.  
  92. fclose(fp);

相对于上一个版本,稍微简单了点


另外b+tree的代码也需要修改(相对于上一章给出的b+tree实现版本https://github.com/begeekmyfriend/bplustree

需要加入int datatype[MAX_ENTRIES];表示数据类型,另外key的类型从int->unsigned long,相应的函数也需要修改一下


总体来说大概就是加入b+tree和hash算法的实现代码bplustee.h/cpp和hash.h/cpp,另外小小的修改一下set和get函数,open和close函数


替换完成,赶紧看看1W个数据的测试时间,可以看出最慢的插入只需要0.07秒,而上一个版本需要7.6秒 快了100倍


这下我们可以试试10W数据了,10W数据只需要0.57秒,而上一个版本需要80秒,快了140倍


再来试试100W数据测试,最慢需要4.1秒



到这里,数据库基本能看了,至少效率比之前好多了接下来还有不少需要优化的地方

附上本章工程http://pan.baidu.com/s/10Obs6

猜你在找的NoSQL相关文章