当前位置: 首页 > java >正文

27、基于map实现的简易kv数据库

#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <filesystem>
#include <random>class KvDataBase {
public:std::map<std::string, std::string> data;// 实现 get 方法,通过键获取值。std::string get(const std::string &key) {auto it = data.find(key);if (it != data.end()) {return it->second;}return "";}// 实现 set1 方法,通过键设置值,若键存在则更新值。bool set1(const std::string &key, const std::string &value) {data[key] = value;return true;}// 实现 set2 方法,通过键设置值,若键存在则不更新值。bool set2(const std::string &key, const std::string &value) {auto result = data.insert({key, value});return result.second;}// 实现 del 方法,通过键删除值。bool del(const std::string &key) {return data.erase(key) > 0;}// 实现 serialize 方法,将数据序列化到文件。bool serialize(const std::string &filename) {std::ofstream ofs(filename, std::ios::binary);if (!ofs.is_open()) {return false;}for (const auto &pair: data) {ofs << "<" << pair.first << ", " << pair.second << ">\n";}ofs.close();return true;}// 实现 deserialize 方法,从文件反序列化数据。bool deserialize(const std::string &filename) {std::ifstream ifs(filename, std::ios::binary);if (!ifs.is_open()) {return false;}data.clear();std::string line;while (std::getline(ifs, line)) {if (line.front() == '<' && line.back() == '>') {line = line.substr(1, line.size() - 2); // 去掉尖括号size_t pos = line.find(", ");if (pos != std::string::npos) {std::string key = line.substr(0, pos);std::string value = line.substr(pos + 2);data[key] = value;}}}ifs.close();return true;}KvDataBase() = default;~KvDataBase() = default;
};void test01() {KvDataBase db;db.set1("key1", "value1");db.set2("key2", "value2");std::cout << "key1: " << db.get("key1") << std::endl;db.del("key1");db.set1("key3", "value3");db.set1("key4", "value4");db.set1("key5", "value5");db.set1("key6", "value6");db.set1("key7", "value7");db.set1("key8", "value8");db.set1("key9", "value9");db.set1("key10", "value10");db.set2("key4", "value467");db.serialize("data.txt");db.deserialize("data.txt");std::cout << "key2: " << db.get("key2") << std::endl;std::cout << "key3: " << db.get("key3") << std::endl;std::cout << "key4: " << db.get("key4") << std::endl;return 0;
}void testInsertPerformance(KvDataBase &db) {auto start = std::chrono::high_resolution_clock::now();for (int i = 0; i < 10000000; ++i) {db.set1("key" + std::to_string(i), "value" + std::to_string(i));}auto end = std::chrono::high_resolution_clock::now();std::chrono::duration<double, std::milli> duration = end - start;std::cout << "插入一千万条数据耗时: " << duration.count() << " ms" << std::endl;
}void testRandomGetPerformance(KvDataBase &db) {std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<> dis(0, 9999);auto start = std::chrono::high_resolution_clock::now();for (int i = 0; i < 100; ++i) {db.get("key" + std::to_string(dis(gen)));}auto end = std::chrono::high_resolution_clock::now();std::chrono::duration<double, std::milli> duration = end - start;std::cout << "随机获取100条数据耗时: " << duration.count() << " ms" << std::endl;
}int main() {KvDataBase db;testInsertPerformance(db);testRandomGetPerformance(db);return 0;
}/*
插入一千万条数据耗时: 14353.8 ms     , 14.3538 s
随机获取100条数据耗时: 0.3669 ms    , 0.0003669 s
*/

为了估算插入1000万条数据大概需要多少内存,我们需要考虑以下几个因素:

  1. 键和值的大小:假设每个键和值都是固定长度的字符串。

  2. std::map 的开销std::map 是基于红黑树实现的,每个节点包含键、值和指向子节点的指针。
    假设每个键和值都是长度为10的字符串(即每个字符串占用10个字符,每个字符1字节),我们可以进行如下估算:

  • 每个键和值的大小:10字节 + 10字节 = 20字节
  • 每个节点的指针开销:假设每个指针占用8字节(在64位系统上),每个节点有3个指针(左子节点、右子节点和父节点),所以指针开销为3 * 8字节 = 24字节
  • 每个节点的总大小:20字节(键和值) + 24字节(指针) = 44字节

因此,插入1000万条数据的总内存开销大约为:

1000万 * 44字节 = 440000000字节 ≈ 419.6 MB

这个估算是一个粗略的近似值,实际内存使用可能会因为其他因素(如内存对齐、额外的元数据等)有所不同。

http://www.xdnf.cn/news/12710.html

相关文章:

  • AIGC的产品设计演进:从工具到协作者
  • 黑马Sting四道练习题
  • 《Progressive Transformers for End-to-End Sign Language Production》复现报告
  • windows使用脚本杀死python进程
  • STM32学习之I2C(理论篇)
  • Addressable-配置相关
  • 操作系统:分页存储管理方式(精简版、含例题)
  • 源码级拆解:如何搭建高并发「数字药店+医保购药」一体化平台?
  • 6.7 打卡
  • AtCoder Beginner Contest 408 D-F 题解
  • JDK8安装与配置
  • 探索Python融合地学:斗之气七段(运算符)
  • 冰箱智能化升级方案:WT3000A离在线AI语音模组赋能AI在线对话功能
  • Cline核心说明文档
  • 基于Java的离散数学题库系统设计与实现:附完整源码与论文
  • mysql整体架构
  • 在 Windows 11 或 10 上将 Visual Studio Code 添加到系统路径
  • C++学习-入门到精通【15】异常处理深入剖析
  • (附实例代码及图示)混合策略实现 doc-doc 对称检索
  • FreeRTOS任务调度过程vTaskStartScheduler()任务设计和划分
  • redis分布式锁
  • Python训练营打卡DAY47
  • 4G物联网模块提升智慧农业的自动化生产效率
  • 【CSS-5】深入理解CSS复合选择器:提升样式表的精确性与效率
  • 第三章支线二 ·函数幻阶:语法召唤与逻辑封印
  • A Execllent Software Project Review and Solutions
  • 函数式接口实现分页查询
  • AI开发 | 生成式AI在企业软件中的演进形态:从嵌入式到智能体
  • nodejs:用 nodemailer 发送一封带有附件的邮件
  • 【JavaSE】集合学习笔记