这学期数据库课程,最后的大程是写一个MiniSQL的数据库实现,要求很简单,建删表,建删单值索引,支持主键和unique定义,支持最简单的select,只要支持3个类型:int,float,char(0~255)。最开始,考虑到数据库的运行时确定类型的特点,选择了运行时强大的C#,还能顺便集成进Linq。但是一周后发现C#操作对象二进制结构的能力几乎为0,在写BufferManager的时候也发现完全不能自由的控制对象生命周期,并且IDisposable的实现也过于迷,与强大运行时和linq相比,这些弱项是我无法接受的,随即果断转到C++。

C++的RAII提供了精确的对象生命周期和所有权控制,这使我很愉快地写出了能精确控制每一个内存块的BufferManager,智能指针,尤其是unique_ptr在其中起到了巨大的作用,还顺便了解了C++11更加精细的对象左右值的概念,更加熟悉了对象所有权和所有权转移的界定和控制。C++足够接近底层的指针和内存操作,也使得我能直接将一个对象指针reinterpret_cast成byte*,随后直接用二进制模式写回文件(当然这里面我手动控制了对象不能有指针和堆内存),也可以从文件中读入一段二进制内容,直接将首地址reinterpret_cast成对象指针,然后直接使用。模板在其中也帮了很大的忙。

索引的部分,最开始使用了模板B+树,随后发现数据库需要运行时类型,模板这种编译时静态类型的东西不能满足我的需求,于是让模板继承自公用的基类,擦除模板类型,基类的虚函数参数使用byte*,擦除参数类型,通过虚函数调用找到正确的派生类后再由派生类恢复参数的类型参与运算,这样算是一种应急的walk around,毕竟当时的时间不允许我把模板容器改成运行时动态类型容器,也没有时间再造一个动态类型轮子。在把运行时的值转为静态的模板类型时,费了很大的劲,主要是需要实现类似于

template<typename T>
TreeBase* make_tree();switch(type)
{
case Int:return make_tree<int>();
case Float:return make_tree<float>();
case Char:switch(size){case 1:return make_tree<array<char, 1>>();case 2:return make_tree<array<char, 2>>();//.....case 255:return make_tree<array<char, 255>>();}break;
}

类似这样的把动态的值转为静态类型的东西,最恶心的部分是那个switch(size)的部分,要case 1~255,手写的话肯定恶心的要死,于是我写了个模板来做二分搜索,最多6层函数调用就能找到正确的值。糊了这么多,还是为了填当初写了个静态的模板B+树的坑。B+树debug的过程中,使用了VS Debugger提供的natvis可视化工具,来自定义我自己写的类在监视窗口中的显示方式,这东西确实爽,看东西方便了不少。

模板B+树的实现内部坑更多,当初的设计是既然所有类型都是静态的,那就可以静态的确定一个树的节点的度,并且可以使得节点大小正好撑满4KB空间,实现起来出了坑,因为迷之内存对齐占据了空间,使用(4KB – sizeof(非指针成员))/sizeof(指针大小)的方式确定的树节点,总是会使得大小超过4KB,幸亏提前猜到了可能出现这样的问题,加了static_assert,不然又不知道要debug到哪里去,话说回来,最后用了#pragma pack(1)这种坑爹货,关了内存对齐,勉强绕过了这个问题。下面的坑就是来自树节点本身,由于我要把整个节点直接二进制写入文件,所以至少需要保证节点是POD类型(虽然后面发现这样做其实多此一举,还增加复杂度),这也就导致了节点内不能放任何成员函数,于是我又写了一个包装类,持有一个树节点,然后在这个包装类里写需要的成员函数,由于树操作需要同时读多个节点,每个节点是一个block,为了防止读后面节点时前面要用的节点被回收的情况出现,我设计了在包装类在包装节点时自动给节点加锁的机制,这有些类似于shared_ptr的引用计数,随后包装类的锁计数控制又出了坑,这让我明白原来不写的move ctor编译器是会自动生成,而不是把move操作变为copy,因此这里有点怀疑老版C++代码中如果做了类似引用计数的机制,是否能直接在C++11环境下正常运行。

解释器的部分手写了tokenizer,用了vczh轮子叔在他博客里给tinymoe写tokenizer时手写状态机的方法,语法分析是单纯的递归下降同时解释执行。

剩下的部分就不具备太多的技术含量,只是单纯的业务逻辑,唯一的坑点就是我在这个数据库里写了三份管理字符串到数字映射的东西,竟然没想到用hash来做,失败,失败。

最后的测试和运行阶段,跑了一遍VS自带的性能分析工具,真的找到了限制性能的地方,是在lru算法替换文件块的部分,被替换块的选择出了坑,导致块交换频率过高,拉低了程序性能,优化之后,插入1W条数据的同时检查3个unique键并插入索引,只需要20秒多一点,还是比较满意的。

写这个东西的过程中还是发现了C++标准库有很多缺少的东西的,比如序列化(这个在未来有了static reflection应该会有所改善,当然现在也有很多序列化开源库),比如花式拼接字符串(sstream太慢),比如二进制文件流(boost有个buffer_stream,但是太老),比如运行时确定规模并且存储空间连续的二(多)维数组(new是不能new int[m][n]的,n必须是字面值),还有char*和string转换时的麻烦等。

一个人handle这样一个最终写了5000多行的东西,中间用到了各种自己学到的C++技术,尝试了各种从前没用过的工具比如natvis,profiler,还在debug B+树的时候刷了夜,解锁了一大堆成就,虽然最后数据库的分数不是很高(我猜多半是我期中期末考得太烂了,大程目测分不低),还是感觉很有收获的,说了这么多,最后以一句vczh轮子叔曾经说过的话做结尾吧。

你需要花时间做什么,取决于这个问题是不是够难,是不是刚刚好你可以做出来,再难一点点你就做不出来了。只要你保持这种训练方法长达十年,想不牛逼都难。

转载于:https://www.cnblogs.com/pointer-smq/p/5651877.html

独自handle一个数据库大程有感相关推荐

  1. java大作业用jsp数据库java_JSP数据库大作业 - 不是太阳也要发光的个人页面 - OSCHINA - 中文开源技术交流社区...

    本人QQ:240814476  欢迎大家提问,共同学习,共同进步. 最近做了一个数据库大作业啊,想用JSP做,发现代码量好大,在做前台的时候感觉手忙脚乱,没时间. 可能是本人拖了太久的原因吧 . 做的 ...

  2. 陶大程:判断人工智能是否可信的“四把尺子”

    作者 | 维克多 编辑 | 青暮 在2021年世界人工智能大会的可信AI论坛上,陶大程进行了主题为<可信人工智能的前世今生>的报告.他在报告中表示,在人工智能的技术落地浪潮中,AI的可信度 ...

  3. 陶大程院士:深度学习“泛化”理论的回顾与前沿

    2020-07-11 22:50:40 作者 | 蒋宝尚 编辑 | 丛 末 2020年7月9日,在世界人工智能大会上,陶大程教授(澳大利亚科学院院士)在科学前沿全体会议上和观众连线,并做了<预见 ...

  4. SDCC 2016系列全回顾:数据库大数据运维架构(附PPT下载)

    2016年9月22日-23日,SDCC2016大数据技术&架构实战峰会将在杭州举行,两场峰会大牛讲师来自阿里.京东.苏宁.唯品会.美团点评.游族.饿了么.有赞.Echo等知名互联网公司,共同探 ...

  5. spring Batch实现数据库大数据量读写

    spring Batch实现数据库大数据量读写 博客分类: spring springBatchquartz定时调度批处理  1. data-source-context.xml Xml代码   &l ...

  6. 我是如何把微服务的这个模式落地的:一个服务一个数据库模式(中)

    从我接触微服务以来,迄今也得有五六年了.断断续续要么从零开始,要么中途接手,也经历了 5 套微服务项目了. 从这些项目中的经验以及和同行交流来看,根据业务切分微服务的方法总的来说思路不复杂,但是落地总 ...

  7. 悉尼大学陶大程:遗传对抗生成网络有效解决GAN两大痛点

    来源:新智元 本文共7372字,建议阅读10分钟. 本文为你整理了9月20日的AI WORLD 2018 世界人工智能峰会上陶大程教授的演讲内容. [ 导读 ]悉尼大学教授.澳大利亚科学院院士.优必选 ...

  8. 新晋 ACM Fellow 陶大程,8 篇 NeurIPS 论文详解

    2019-12-26 06:17:03 作者 | AI科技评论 编辑 | 刘萍 近日2019年 ACM Fellows 增选结果出炉之后,备受人们关注,其中除谢源.周礼栋.陈熙霖等业界和学术界著名学者 ...

  9. 2019 年 ACM Fellow出炉,陈熙霖、陶大程、周礼栋、谢源、李向阳等7位华人学者入选

    纽约时间12月11日,美国计算机学会(ACM)宣布了 2019 年新当选 ACM Fellow 名单,共有 58 位科学家当选,其中包括 7 位华人. 作为世界上最大的计算机领域专业性学术组织,ACM ...

最新文章

  1. java 爬虫 异步_Java 爬虫遇上数据异步加载,试试这两种办法!
  2. 【深度学习】谷歌大脑EfficientNet的工作原理解析
  3. Vmware中安装RHEL5
  4. 将yolo标注转换为tensorflow_yolov3标注生成train.txt和test.txt同时做数据清洗
  5. mysql存储过程——procedure[prəˈsiːdʒər]
  6. 多个小int的乘法小心溢出哦(记洛谷P1615题WA的经历,Java语言描述)
  7. JavaScript常用数组操作
  8. RocketMQ : RemotingTooMuchRequestException: sendDefaultImpl call timeout
  9. linux 备份mysql_linux下备份MYSQL数据库的方法
  10. python包的init文件_Python模块包中__init__.py文件的作用
  11. 聊聊高并发系统之限流特技(二)作者:张开涛
  12. java 代码统计工具_java代码行数统计工具
  13. 内网远程控制安卓设备软件推荐
  14. python 将QQ聊天记录生成词云图
  15. DOOM3源码分析相关文章集合
  16. python 单词纠错_自然语言处理1——语言处理与Python(内含纠错)
  17. 阿里云ECS简易部署教程
  18. 网页挂马的原理和实现方式
  19. 做网站注意事项,网站建设标准流程
  20. moment.js 实现获取近一月、近三月、近一年、一月后、一年后等

热门文章

  1. wxFormBuilder添加wxToolBar报错cpp(963) in wxToolBar::Realize(): invalid tool button bitmap解决方案
  2. Qt 多线程(QThread)
  3. displaytag.properties 文件配置
  4. css3有趣的transform形变
  5. qt中模态对话框和非模态对话框
  6. 【光圈】光圈是什么意思
  7. 西邮共享上网工具不正确使用的后果(如何在西邮免费上网)
  8. Pycharm通过设置实现ctrl+滚动鼠标滑轮缩放字体大小
  9. 空间滤波-几何均值滤波器
  10. 前端开发常用到的flex布局简单范例