基于上一章的内容,我们需要把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秒
到这里,数据库基本能看了,至少效率比之前好多了接下来还有不少需要优化的地方