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

释放双眼,带上耳机,听听看~!

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

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


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

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

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

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


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

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

另外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

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索