NoSQL 技术选型与数据库索引数据结构实战指南——基于 db-tutorial 开源仓库
文档教程数据库【免费下载链接】db-tutorial 后端程序员应该掌握的主流数据库知识项目地址https://gitcode.com/gh_mirrors/db/db-tutorial点击查看免费下载本文以 db-tutorial 项目数据库综合章节的两篇核心文档Nosql 技术选型 与 数据结构与数据库索引为主体系统梳理五大类 NoSQL 数据库的适用边界与选型策略并深入剖析哈希索引、B 树、LSM 树、倒排索引等底层数据结构的工作原理。读完本文你将掌握按业务需求而非技术偏好的数据库选型方法论并能从数据结构层面理解不同数据库读写性能差异的根因直接指导缓存、搜索、日志、社交等系统的存储方案设计。一、为什么需要 NoSQL关系型数据库的五大短板传统的关系型数据库RDBMS凭借 ACID 事务与 SQL 标准统治了应用开发数十年但在大数据与高并发场景下其固有架构暴露出以下问题详见 Nosql 技术选型大数据场景下 I/O 较高数据按行存储即使只针对某一列运算也会将整行数据从存储设备读入内存导致无谓的 I/O 消耗。无法存储数据结构只能存储行记录难以直接表达 List、Map、Set 等结构化的内存模型。表结构 schema 扩展不方便修改表结构需要执行 DDL 语句修改期间会锁表导致部分服务不可用。全文搜索功能较弱只能做子字符串匹配LIKE数据量增大后LIKE匹配极慢即使有索引且关系型数据库本就不适合对文本字段建索引。存储和处理复杂关系型数据功能较弱社交应用、推荐引擎、欺诈检测、知识图谱等用例需要导航高度连接的数据关系而关系型数据库的表格模型与严格 schema 使其难以添加新的关联信息种类。随着大数据时代的到来海量数据存储、高并发请求、高可用与高可扩展性成为刚需传统关系型数据库力不从心。于是NoSQLNot Only SQL非关系型数据库作为关系型数据库的有力补充迅速崛起。需要强调的是NoSQL 在补足关系型短板的同时往往也伴随特性缺失最常见的就是事务功能缺失——数据库事务正确执行的四个基本要素 ACID 如下要素名称描述AAtomicity原子性一个事务中的所有操作要么全部完成要么全部不完成不会在中间某个环节结束执行出错会回滚到事务开始前的状态CConsistency一致性事务开始之前和结束之后数据的完整性约束没有被破坏IIsolation隔离性数据库允许多个并发事务同时对数据读写和修改隔离性可防止并发交叉执行导致的数据不一致DDurability持久性事务处理结束后对数据的修改就是永久的即便系统故障也不会丢失选型的核心原则是以需求为导向基于业务驱动架构。无论选用 RDB、NoSQL 还是 NewSQL最终方案必然是数据量、并发、一致性、实时性等多维权衡下的综合性设计。下面逐一剖析五大类 NoSQL 数据库如何对症下药。二、列式数据库解决大数据 I/O 高问题列式数据库以列相关存储架构进行数据存储主要适合批量数据处理和即时查询与之对应的行式数据库以小批量数据处理为主常用于联机事务型处理OLTP。基于按列存储的特性列式数据库可解决特定场景下关系型数据库 I/O 较高的问题。2.1 存储原理行存储 vs 列存储传统关系型数据库按行存储行存储法将各行放入连续的物理位置类似传统记录和文件系统列式数据库则按列存储。两者最大的差异在于磁盘读取模式读取多条数据的同一列时列式存储的列数据聚集在一起一次磁盘操作即可把指定列全部读入内存这正是查询效率高的根源。2.2 代表产品HBase 与 BigTableHBase开源的非关系型分布式数据库NoSQL参考谷歌 BigTable 建模由 Java 实现是 Apache 软件基金会 Hadoop 项目的一部分运行于 HDFS 之上可为 Hadoop 提供类似 BigTable 规模的服务能容错地存储海量稀疏数据。BigTable谷歌基于 GFS 的压缩、高性能、高可扩展数据存储系统用于存储大规模结构化数据适用于云端计算。2.3 核心特性高压缩率与高查询效率优点高效的存储空间利用率列式数据库针对不同列的数据特征采用不同算法压缩率通常远高于行式数据库行式约 3:15:1列式可达 8:130:1。典型手段是字典表压缩——将重复字符串映射为数字每个字符串在字典表中只出现一次从而达成压缩目的。查询效率高同一列的多个值聚集存储一次磁盘操作即可读入整列配合数据压缩后一次查询的执行链路为① 去字典表找字符串对应的数字仅一次字符串比较→ ② 用数字去列表匹配命中位置记为 1 → ③ 对不同列的匹配结果做位运算得到满足所有条件的记录下标 → ④ 用该下标组装最终结果集。适合聚合操作、适合大量数据而非小数据。缺点不适合扫描小量数据、不适合随机更新、不适合含删除和更新的实时操作。事务支持不完整单行数据是 ACID 的多行事务不支持正常回滚支持 I隔离性事务串行提交与 D持久性但不能保证 A原子性与 C一致性。2.4 使用场景以 HBase 为例大数据量百 TB 级且有快速随机访问需求增长量无法预估、需要优雅横向扩展的应用HBase 支持在线扩展数据井喷式增长也能通过横向扩展满足。写密集型应用每天写入量巨大而读取量相对较小如 IM 历史消息、游戏日志等。不需要复杂查询条件的应用HBase 只支持基于 rowkey 的查询单条或小范围查询可接受不适用于 join、多级索引、复杂表关系的数据模型。对性能和可靠性要求极高的应用HBase 本身无单点故障可用性非常高。存储结构化和半结构化数据。仓库佐证db-tutorial 在 codes/javadb/hbase 目录下提供了完整的 HBase Java 操作示例未使用 ORM。其中 RowType.java 定义了四种主键rowkey生成策略恰好呼应了基于 rowkey 查询这一 HBase 核心特性ORIGIN_ID原 ID用 0 左补齐到指定长度适合保留业务原始主键TIMESTAMP以 10 位秒级时间戳作为 ID数据存储单调递增适合以 scan 为主、数据量不大100w 以内、读频率不高的场景UUIDUUID 主键适合数据量较大且以 get 为主的场景尽量保证数据离散分布BUCKETID bucket(2/3) timestamp(10) bizId适合数据量较大且需要大量 scan 的场景需在TableId中指定分桶数。具体拼接逻辑见 RowKeyUtil.javaORIGIN_ID 用padPre左补零BUCKET 模式先对业务 ID 取 FNV 哈希取模得到桶号再拼接。实体类只需实现 BaseHbaseEntity.java 接口即可获得getRowKey()能力而 CommonMapper.java 则提供了insertBatch、getListByIds等按 ID 批量操作的通用接口——印证了 HBase 以 rowkey 为核心的读写模型。三、K-V 数据库解决无法存储数据结构问题K-V 数据库以键值对key-value形式组织、索引和存储数据非常适合存储不涉及过多数据关系的数据能有效减少读写磁盘的次数读写性能优于 SQL 数据库弥补了关系型数据库无法存储数据结构的短板。3.1 代表产品Redis、Cassandra 与 LevelDBRedis使用 ANSI C 编写的开源、支持网络、基于内存、可选持久化的键值对存储数据库是当前最流行的键值对存储数据库之一。Cassandra开源分布式 NoSQL 数据库集 Google BigTable 的数据模型与 Amazon Dynamo 的完全分布式架构于一身最初由 Facebook 开发用于储存收件箱等简单格式数据后被众多知名站点采用。LevelDBGoogle 研发的嵌入式键值对数据库编程库以 BSD 许可证开源。3.2 核心特性以 Redis 为例优点性能极高可支撑超过 10W 的 TPS。丰富的数据类型支持 String、Hash、List、Set、Sorted Set、Bitmap、HyperLogLog 等。丰富的特性支持发布/订阅publish/subscribe、通知、key 过期等。缺点针对 ACIDRedis 事务不能支持原子性和持久性A 和 D只支持隔离性和一致性I 和 C。特别说明这里无法保证原子性是指 Redis 的事务操作——因为事务不支持回滚roll back而由于 Redis 的单线程模型Redis 的普通操作是原子性的。关键认知大部分业务并不需要严格遵循 ACID。例如游戏实时排行榜、粉丝关注等场景即使部分数据持久化失败业务影响也很小。因此设计方案时应根据业务特征和要求做选择。3.3 使用场景适用场景存储用户信息如会话、配置文件、参数、购物车等——这些信息一般都与 ID键挂钩。不适用场景需要通过值来查询而不是键——K-V 数据库没有按值查询的途径需要存储数据之间的关系——不能通过两个及以上键来关联数据需要事务支持——故障发生时无法回滚。仓库佐证db-tutorial 的 codes/javadb/redis 提供了 Redis 的 Spring Boot 集成示例。以 UserServiceImpl.java 为例用户信息直接以spring-boot:user为 Hash 键、用户 ID 为 field 存储public static final String DEFAULT_KEY spring-boot:user; private final RedisTemplate redisTemplate; public User getUser(Long id) { return (User) redisTemplate.opsForHash().get(DEFAULT_KEY, id.toString()); } public void setUser(User user) { redisTemplate.opsForHash().put(DEFAULT_KEY, user.getId().toString(), user); }这正是 K-V 数据库典型用法用户信息与 ID 强挂钩按键直接读写。仓库还提供了 Redis 数据类型和应用 等教程文档以及 redis-config 下哨兵Sentinel三节点的高可用配置示例供进一步实践。四、文档数据库解决schema 扩展不方便问题文档数据库Document-Oriented Database旨在将半结构化数据存储为文档通常以JSON 或 XML 格式存储数据从而解决关系型数据库表结构 schema 扩展不便的问题。由于 no-schema 特性可以存储和读取任意数据无需在使用前定义字段读取一个 JSON 中不存在的字段也不会导致 SQL 那样的语法错误。4.1 代表产品MongoDB 与 CouchDBMongoDB面向文档的数据库管理系统由 C 撰写数据以类似 JSON 的 BSON 格式存储可描述较复杂的数据结构。CouchDBApache 开源数据库以 JSON 作为存储格式、JavaScript 作为查询语言、MapReduce 和 HTTP 作为 API显著功能包括多主复制。4.2 核心特性以 MongoDB 为例优点容易存储复杂数据结构JSON 是强大的描述语言能描述复杂数据结构。容易变更数据结构无需先执行 DDL 修改表结构程序代码直接读写即可。容易兼容历史数据历史数据即使没有新增字段也不会报错只会返回空值代码兼容处理即可。缺点部分支持事务原子性A仅支持单行/单文档级别不支持多行、多文档、多语句原子性隔离性I仅支持已提交读Read committed可能导致不可重复读与幻读。MongoDB 仍支持多文档事务的一致性C与持久性D。不支持复杂查询例如 join 查询需要多次操作数据库。补充事实原文档写作时 MongoDB 官方宣布将在 4.0 版本正式推出多文档 ACID 事务支持落地情况以官方版本发布为准——这也说明文档数据库的事务能力始终在演进中。4.3 使用场景适用场景大数据量且未来数据增长很快表结构不明确、字段持续增加如内容管理系统、信息管理系统。不适用场景需要在不同文档间添加事务需要多文档间的复杂查询如 join。仓库佐证db-tutorial 的 codes/javadb/mongodb 覆盖了 MongoDB 的聚合、投影、Query by Example、文本搜索等高级用法。以 aggregation/Order.java 为例实体类仅靠Document注解映射集合内嵌ListLineItem items描述订单明细——无需预先定义表结构这正是文档模型轻松存储复杂嵌套结构的直接体现Data AllArgsConstructor(onConstructor __(PersistenceConstructor)) Document public class Order { private String id; private String customerId; private Date orderDate; private ListLineItem items; ... }对应教程见 MongoDB 教程 下的 MongoDB 的 CRUD 操作、MongoDB 聚合操作、MongoDB 事务 等章节。五、全文搜索引擎解决全文搜索功能弱问题关系型数据库在全文搜索场景下索引也无能为力全文搜索的条件可随意排列组合索引数量会爆炸模糊匹配只能靠LIKE整表扫描效率极低。全文搜索引擎正是为补齐这一短板而生。5.1 核心原理倒排索引inverted index全文搜索引擎的技术原理称为倒排索引一种建立单词 → 文档映射的索引方法与之相对的正排索引建立的是文档 → 单词映射。正排索引以文档为维度列出文档包含的单词适用于根据文档名称查询文档内容。倒排索引以单词为维度记录每个单词出现在哪些文档中适用于根据关键词查询文档内容。简单的倒排索引仅维护单词到文档列表的映射进一步可加入单词频率term frequency信息用于相关性排序与打分。5.2 代表产品Elasticsearch 与 SolrElasticsearch基于 Lucene 的分布式搜索引擎提供全文搜索的 HTTP Web 接口与无 schema 的 JSON 文档用 Java 开发、Apache License 开源是当前主流的企业级搜索引擎之一。SolrApache Lucene 项目的开源企业搜索平台主要功能包括全文检索、命中标示、分面搜索、动态聚类、数据库集成以及富文本Word、PDF处理高度可扩展支持分布式搜索与索引复制。5.3 核心特性以 Elasticsearch 为例优点查询效率高对海量数据进行近实时处理。可扩展性基于集群环境可方便横向扩展可承载 PB 级数据。高可用集群具备弹性能自动发现新增或故障节点重组并重新平衡数据确保数据安全可访问。缺点部分支持事务单文档数据是 ACID 的多文档事务不支持正常回滚支持 I隔离性基于乐观锁机制与 D持久性不支持 A原子性与 C一致性。对类似数据库中通过外键的复杂多表关联操作支持较弱。读写有一定延时写入的数据最快 1s 内可被检索到。更新性能较低底层实现是先删除旧数据再插入新数据。内存占用大Lucene 将索引部分加载到内存中。5.4 使用场景适用场景搜索引擎与数据分析引擎全文检索、结构化检索、数据分析对海量数据进行近实时处理分散到多台服务器存储和检索。不适用场景数据需要频繁更新需要复杂关联查询。仓库佐证db-tutorial 的 codes/javadb/elasticsearch 提供了 elasticsearch6 与 elasticsearch7 两套示例。以 elasticsearch7 为例UserRepository.java 通过继承 Spring Data 的ElasticsearchRepository即可获得声明式全文检索能力public interface UserRepository extends ElasticsearchRepositoryUser, String { ListUser findByUserName(String UserName); User findByEmail(String email); }配套教程见 Elasticsearch 教程 下的 Elasticsearch 快速入门、Elasticsearch 索引、Elasticsearch 查询 等章节仓库还提供了 elasticsearch docker-compose 配置 便于本地起环境验证。六、图数据库解决复杂关系数据处理弱问题图形数据库应用图论存储实体之间的关系信息最常见例子是社会网络中人与人之间的关系。关系型数据库存储关系型数据效果不佳——查询复杂、缓慢、超出预期图数据库的独特设计正好弥补了这一缺陷。6.1 代表产品Neo4j、ArangoDB 与 TitanNeo4j由 Neo4j, Inc. 开发具有原生图存储与处理能力、符合 ACID 的事务数据库是最流行的图形数据库之一。ArangoDB原生多模型数据库系统同时支持键值、文档、图形三种数据模型使用统一查询语言 AQLArangoDB Query Language允许在单个查询中组合不同数据访问模式。Titan可扩展的图形数据库针对存储和查询分布在多机集群中的数百亿顶点与边进行优化可支持数千并发用户实时执行复杂图遍历。6.2 核心特性以 Neo4j 为例Neo4j 使用图graph的概念建模两个最基本概念是节点Node与边Edge/Relationship节点表示实体边表示实体间关系两者都可拥有属性。不同实体通过各种关系关联形成复杂的对象图。针对关系数据关系型数据库与图数据库的存储结构本质不同。Neo4j 存储节点时采用index-free adjacency免索引邻接每个节点都有指向其邻居节点的指针可在 O(1) 时间内找到邻居节点。按照官方说法Neo4j 中边是最重要的first-class entities被单独存储这有利于图遍历时提速也方便以任意方向遍历。优点高性能图的遍历是图数据结构独有的算法从某节点出发按连接关系快速找出邻近节点由于邻近查询只检索有限的局部数据、不搜索整个数据库查找效率不受数据量大小影响。设计的灵活性数据结构自然伸展、非结构化数据格式使图数据库设计具有很大伸缩性和灵活性需求变化新增的节点、关系及属性不影响原有数据使用。开发的敏捷性直观明了的数据模型从需求讨论、程序开发到最终存储模型形态几乎一致。完全支持 ACID不同于多数 NoSQL 数据库Neo4j 具有完整事务管理特性。缺点存在对节点、关系、属性数量的限制。不支持拆分。6.3 使用场景适用场景关系性强的数据如社交网络推荐引擎以图形式表现数据非常有益于推荐制定。不适用场景记录大量基于事件的数据日志条目、传感器数据对大规模分布式数据做处理保存在关系型数据库中的结构化数据二进制数据存储。七、选型总结需求驱动综合权衡关系型数据库与 NoSQL 的选型往往需要考虑以下指标数据量并发量实时性一致性要求读写分布和类型安全性运维成本常见软件系统的数据库选型参考如下| 系统类型 | 推荐方案 | | :-: | :- | |中后台管理型系统如运营系统 | 数据量少、并发量小首选关系型数据库| |大流量系统如电商单品页 | 后台选关系型数据库前台选内存型数据库K-V | |日志型系统| 原始数据选列式数据库日志搜索选搜索引擎| |搜索型系统如站内商品搜索 | 后台选关系型数据库前台选搜索引擎| |事务型系统如库存、交易、记账 | 关系型数据库 K-V 数据库作缓存 分布式事务 | |离线计算大量数据分析 | 列式数据库或关系型数据库 | |实时计算如实时监控 | 内存型数据库或列式数据库 |五大类 NoSQL 与关系型数据库短板的对应关系可归纳为列式数据库→ 解决大数据场景 I/O 高、支持批量分析与聚合K-V 数据库→ 解决无法存储数据结构、需要高性能缓存与读写文档数据库→ 解决 schema 扩展不便、数据结构频繁变更全文搜索引擎→ 解决全文搜索能力弱、需要近实时检索图数据库→ 解决复杂关系数据处理弱、需要深度关系遍历。设计实践中无论选用 RDB/NoSQL/NewSQL一定是以需求为导向最终数据存储方案必然是各种权衡的综合性设计。八、数据结构与数据库索引读写的底层逻辑理解了选什么数据库还需理解为什么这么设计。数据库本质上只负责两件事读数据、写数据而数据结构研究的是如何合理组织数据、提升读写效率这正是数据库的核心问题。索引是数据库为了提高查找效率而引入的一种数据结构如同书的目录它的作用是缩小检索范围、提升查询性能。索引对于性能非常关键——数据量小且负载低时不恰当的索引影响不明显数据量增大后性能会急剧下降因此索引优化是查询性能优化的最有效手段。同时要认识到索引的代价维护额外结构会引入开销任何类型的索引通常都会降低写入速度每次写数据都需更新索引甚至难以超过简单的追加文件方式。8.1 数组与链表两种极端都不适合直接做索引数组用连续内存空间存储数据支持随机访问按下标访问时间复杂度 O(1)。但查找未必是 O(1)无序数组只能顺序查找O(n)有序数组可二分查找O(log n)。既然有序数组 二分查找如此高效为何几乎没有数据库直接用数组做索引因为要保持有序每次插入/删除都需要移动数据时间复杂度 O(n)且数组空间固定扩容只能复制数组。这些特性决定了数组不适合数据频繁变化的场景。链表用不连续的内存空间存储数据通过指针按顺序串联各结点。优点是插入/删除 O(1)不必按顺序存储缺点是其低效的查找只能顺序访问查找 O(n)决定了它不适合作为索引。8.2 哈希索引等值查询的极致但只适用于特定场合哈希表使用哈希函数组织数据将 key 经 Hash 函数转换为数组下标利用数组随机访问特性在O(1)时间内完成检索。哈希表分为哈希集合存储非重复值与哈希映射存储键值对。哈希索引基于哈希表实现只适用于等值查询对每行数据将索引列计算一个较小的哈希码hashcode哈希码存于索引中哈希表保存指向每个数据行的指针。✔优点索引数据结构紧凑查询速度非常快。❌缺点索引只含哈希值和行指针、不含字段值不能仅靠索引避免读取行但访问内存中的行很快影响通常不大数据不按索引值顺序存储无法用于排序不支持部分索引匹配哈希计算使用索引列全部内容如 (A,B) 上建哈希索引仅查 A 无法使用只支持等值比较、IN()、不支持范围查询如WHERE price 100可能出现哈希冲突冲突时需遍历链表中所有行指针逐行比较冲突多时索引维护代价高。因此哈希索引只适用于特定场合例如 MySQL 的 Memory 存储引擎显式支持哈希索引而一旦适用性能提升会非常显著。仓库中 Redis 实战 所讲的缓存与分布式锁场景正是建立在哈希/K-V 结构 O(1) 读写特性之上。8.3 B-Tree 与 BTree 索引关系型数据库的支柱通常所说的 B 树索引指B-Tree索引是目前关系型数据库最常用有效的索引。注意MySQL 在CREATE TABLE等语句中使用B-Tree关键字但不同存储引擎实际结构不同——InnoDB 使用 BTreeMyISAM 使用 B-Tree。B-Tree的 B 指 balance平衡。B-Tree 索引找到的不是具体行而是数据行所在页数据库把页读入内存再查找。从二叉搜索树到多路搜索树二叉搜索树的查询复杂度为 O(log n)但为维持平衡更新复杂度也是 O(log n)。随着数据增长索引只能以文件形式存于磁盘索引查找会产生磁盘 I/O——相对内存存取I/O 消耗高几个数量级。几百万节点的二叉树深度很大每读一个节点一次 I/O耗时不可接受。有效解法是减少树深度把二叉树变为 N 叉多路搜索树B 树正是多路搜索树。理解 BTree 只需抓住两个特征所有关键字数据都存储在叶子节点非叶子节点不存真正数据所有记录节点按键值大小顺序存放在同一层叶子节点上所有叶子节点由指针连接形成有序链表。根据叶子节点内容索引分为主键索引与非主键索引聚簇索引clustered又称主键索引叶子节点存整行数据。由于无法把数据行同时放在两个地方一个表只能有一个聚簇索引。InnoDB 的聚簇索引实际是在同一结构中同时保存 B 树索引和数据行。数据与相邻键值紧凑存储访问快。非主键索引二级索引 secondary叶子节点内容是主键的值。数据与索引分离存储索引含指向数据存储位置的指针可以有多个InnoDB 中一般小于 249 个。聚簇索引与非聚簇索引查询的区别select * from T where ID500聚簇索引查询只需搜索 ID 这棵 B 树select * from T where k5非聚簇索引查询先搜索 k 索引树得到 ID500再到 ID 索引树搜索一次——这个过程称为回表。也就是说基于非聚簇索引的查询需要多扫描一棵索引树因此应用中应尽量使用主键查询。显然主键长度越小非聚簇索引的叶子节点越小占用空间越小。自增主键NOT NULL PRIMARY KEY AUTO_INCREMENT从性能与存储空间考量往往是更合理的选择。但有一种场景适合用业务字段直接做主键只有一个索引且该索引必须是唯一索引——因无其他索引不必考虑叶子节点大小此时可直接将该索引设为主键避免每次查询搜索两棵树。为什么 B 树适合磁盘磁盘是机械器件访问需等盘片旋转到磁头下随机读写与内存相比有 10 万到 100 万倍左右的差距但顺序访问大批量数据时磁盘性能与内存同一数量级。磁盘最小读写单位是扇区早期 512 字节目前常见 4K操作系统最小读写单位是块Block也叫簇 Cluster——读取数据时操作系统会一次性读出整个块。因此高效检索磁盘数据的重要原则是对磁盘的访问次数要尽可能少。B 树正是为此设计让一个节点的大小等于一个块的大小节点内存储的不是一个元素而是一个可容纳 m 个元素的有序数组使磁盘一次读取的数据被充分利用。同时将节点分为内部节点与叶子节点内部节点仅存 key 和维持树形结构的指针可容纳更多索引数据用最少内部节点组织全部数据叶子节点仅存 key 和数据、不存树形指针实现空间利用率最大化。再加上同一层节点串成有序双向链表B 树同时具备良好的范围查询能力与灵活调整能力。因此B 树是一棵完全平衡的 m 阶多叉树每个节点最多 m 个子节点每个节点内含紧凑的可装 m 个元素的有序数组。若 B 树完全加载在内存中其检索效率并不会比有序数组或二叉检索树更高同样二分查找的 log(n) 效率反而更复杂、有额外开销——其价值在于磁盘友好。此外这一节还蕴含一个重要的设计思想索引和数据分离——将索引数组控制在较小范围内以便加载进内存许多大规模系统都用此思路精简索引B 树内部节点与叶子节点的区分也是索引与数据分离的一次实践。MySQL 的两种实现MyISAM 引擎的 B 树叶子节点仅存数据位置指针是索引与数据分离的非聚集索引为保证数据一致性需要在表级别加锁InnoDB 的 B 树叶子节点直接存具体数据是索引与数据一体的聚集索引因数据直接在索引叶子节点中只需支持行级锁即可保证一致性。更完整的索引策略何时使用索引、索引优化手段可继续阅读 Mysql 索引 与 Mysql 性能优化。8.4 LSM 树以顺序写换写性能的 NoSQL 引擎B 树的数据都在叶子节点、叶子节点多在磁盘上因此每次插入新数据都需要随机写入磁盘随机写入性能极慢。对每秒钟写入上千上万条的日志系统来说这种代价会使性能急剧下降。LSM 树Log Structured Merge Trees的思路是能否以块为单位写入而不是每次插入都随机写盘其机制是——数据写入时延迟写磁盘先放在内存中的树里做常规存储和查询当内存树持续变大达到阈值时再批量以块为单位写入磁盘中的树。因此 LSM 树至少由两棵树组成存储在内存中较小的C0 树和存储在磁盘中较大的C1 树。LSM 树的三个特点索引分为内存和磁盘两部分内存达到阈值时启动树合并Merge Trees用批量写入代替随机写入并用预写日志WALWrite Ahead Log技术保证内存数据在系统崩溃后可恢复数据以日志追加写的方式写入磁盘Log Structured以顺序写提高写入效率。这些特点使 LSM 树相比 B 树在写入性能上大幅提升因此许多 NoSQL 系统都使用 LSM 树作为检索引擎并对其做优化以提升检索性能。这与列式数据库适合写密集型应用如 HBase 的日志、IM 历史消息场景正好相互印证——写友好的引擎支撑写密集的列式存储。8.5 倒排索引搜索引擎与全文检索的基石倒排索引的核心并不复杂其具体实现其实是哈希表——但不是以文档 ID 或题目为 key而是反过来以内容或属性为 key 存储对应的文档列表从而在 O(1) 时间代价内完成查询。数据库的全文索引功能、搜索引擎索引、广告引擎和推荐引擎都使用倒排索引实现检索。结合前文全文搜索引擎一节可见Elasticsearch 的高效全文检索正是建立在这一数据结构之上。8.6 索引的维护创建与更新策略创建索引的两大方向数据压缩尽可能将数据加载到内存中内存检索效率远高于磁盘索引压缩是重要研究方向分支处理将大数据集合拆成多个小数据集合处理这其实就是分布式系统的核心思想。更新索引的两种机制Double Buffer双缓冲机制内存中同时保存两份一样的索引索引 A 和 B一个读、一个写并来回切换完成高性能索引更新。优点是简单高效缺点是达到一定数据量级后带来翻倍的内存开销索引存在磁盘上时更是无法使用。全量索引 增量索引将新接收数据单独建立可驻留内存的倒排索引增量索引查询时同时查询全量索引和增量索引合并结果输出。因增量索引远小于全量索引内存消耗可承受可对其应用 Double Buffer 机制实现无锁访问全量索引本身只读无需加锁整个检索过程无锁访问从而提升检索效率。九、总结与仓库导航本文完整梳理了 db-tutorial 项目数据库综合主题的两大知识板块五大类 NoSQL 数据库列式、K-V、文档、搜索引擎、图的优缺点与选型策略以及支撑数据库读写的核心数据结构哈希表、B 树、LSM 树、倒排索引。选型没有银弹——数据量、并发量、实时性、一致性、读写分布、安全性、运维成本七大指标需要综合权衡而理解了索引的数据结构原理才能真正理解为什么 InnoDB 用 B 树、NoSQL 用 LSM 树、搜索引擎用倒排索引。若想进一步动手实践可结合 db-tutorial 仓库的以下资源深入综合导航数据库综合 README即本文主题来源、Nosql 技术选型、数据结构与数据库索引关系型数据库Mysql 教程、Mysql 索引、Mysql 性能优化文档数据库MongoDB 教程 及 codes/javadb/mongodb 示例K-V 数据库Redis 教程 及 codes/javadb/redis 示例、redis-config 哨兵配置列式数据库HBase 教程 及 codes/javadb/hbase 示例搜索引擎数据库Elasticsearch 教程 及 codes/javadb/elasticsearch 示例、docker-compose 环境Java 示例总览javadb READMEH2、HBase、MongoDB、MySQL、Redis、SQLite 的 Java 操作示例未使用 ORM。赞分享文档教程数据库【免费下载链接】db-tutorial 后端程序员应该掌握的主流数据库知识项目地址https://gitcode.com/gh_mirrors/db/db-tutorial点击查看免费下载相关推荐NoSQL 技术选型终极指南db-tutorial 帮你选择最适合的数据库NoSQL 技术选型终极指南db tutorial 帮你选择最适合的数据库 随着大数据时代的到来越来越多的应用系统需要支撑海量数据存储、高并发请求、高可用和文档教程数据库数据库索引设计与优化db-tutorial 数据结构深度解析数据库索引设计与优化db tutorial 数据结构深度解析 数据库索引是提升查询性能的关键技术理解其底层数据结构对于设计高效的数据库系统至关重要。本文基于文档教程数据库KittenPHP-DB-Engine与NoSQL数据库对比技术选型的决策指南KittenPHP DB Engine与NoSQL数据库对比技术选型的决策指南 在当今快速发展的互联网时代选择合适的数据库技术对于项目的成功至关重要。Kit编译器后端数据库上一篇openEuler/ubutils开发指南从源码解析到自定义功能实现的终极教程下一篇cu-scanner安全加固终极指南防止数据泄露与未授权访问的10个关键步骤创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Java+SpringBoot白酒物料管理系统设计与实现

Java+SpringBoot白酒物料管理系统设计与实现

1. 项目背景与选题价值洋河酒厂作为国内知名白酒生产企业,其酿酒物料管理具有典型的行业特性。传统的手工记录方式存在数据滞后、统计困难、追溯性差等问题,直接影响生产计划制定和成本核算精度。我们团队开发的这套基于Java的物料管理系统,正…

2026/10/13 9:44:48 阅读更多 →
傅里叶变换学习笔记:用线性代数理解量子力学位置动量表象

傅里叶变换学习笔记:用线性代数理解量子力学位置动量表象

我的书桌上现在摊着两本笔记:左边是线性代数,右边是量子力学。标题里“线性代数 or 量子力学”其实是个伪命题,因为这两本笔记翻到后面,都会跳出一个共同的名字——傅里叶。这篇外传要写的,就是我从一次跨学科复习中整…

2026/10/13 9:44:48 阅读更多 →
AI时代个人量化入门:从零开发适合你的交易策略

AI时代个人量化入门:从零开发适合你的交易策略

AI时代最大的红利:个人做量化,也能开发出一套适合你的策略讲点实在的。这两年身边越来越多的朋友问我,说看到网上那些AI量化、程序化交易的内容,自己也心动,但总觉得这东西门槛高——要么觉得得是数学博士才能碰&#…

2026/10/13 9:44:48 阅读更多 →

最新新闻

拼多多商家自研接口申请教程(2026最新版):从注册到调通API全流程踩坑记录

拼多多商家自研接口申请教程(2026最新版):从注册到调通API全流程踩坑记录

关键词:拼多多开放平台 商家自研 ERP对接 API申请 pdd接口 最近公司要把拼多多店铺的订单、库存、物流全部收到自研ERP里统一管理,研究了一圈拼多多开放平台,发现"商家自研"这条路其实门槛不高,但官方文档写得比较散,中…

2026/10/13 10:29:05 阅读更多 →
Spring Boot + MyBatis 整合实践:从自动装配到事务与连接池调优

Spring Boot + MyBatis 整合实践:从自动装配到事务与连接池调优

简介:这套Spring Boot与MyBatis的整合模板,面向需要快速搭建后端数据接口的Java工程师,也适合作为项目开发的基础骨架。项目利用Spring Boot的自动配置简化依赖管理与启动流程,将MyBatis作为持久层框架,通过Mapper接口…

2026/10/13 10:29:05 阅读更多 →
Spring Boot + MyBatis 数据访问层实战:配置、踩坑与性能优化

Spring Boot + MyBatis 数据访问层实战:配置、踩坑与性能优化

简介:面向Java Web后端开发者,这是一套SpringBoot与MyBatis整合的项目示例,围绕高效微服务开发场景,引入Druid连接池与Swagger接口文档工具,可降低项目初期配置成本,统一数据持久层访问,并为API…

2026/10/13 10:29:05 阅读更多 →
64位PowerShell避坑指南:从32位进程架构到内存溢出与注册表重定向

64位PowerShell避坑指南:从32位进程架构到内存溢出与注册表重定向

简介:面向仍在使用Windows Server 2003等旧版64位系统的运维人员与开发者,这是一份难得的Windows PowerShell 64位安装包。该压缩包恰好补足了微软官方不再为这些老系统提供下载的缺口,共包含2个文件:PowerShell_Setup_amd64.msi安…

2026/10/13 10:29:05 阅读更多 →
C# WinForms+SQLite设备管理系统开发:台账、维修与报表全攻略

C# WinForms+SQLite设备管理系统开发:台账、维修与报表全攻略

简介:这是一套基于C#与ASP.NET的Web设备管理系统完整源码工程,主要面向C#初中级学习者、高校软件相关专业学生以及需要快速搭建设备管理后台的开发者。系统覆盖设备档案维护、借用归还登记、维修工单处理和报表统计等典型管理环节,源码中充分…

2026/10/13 10:29:05 阅读更多 →
Oracle rownum与rowid底层原理与实战避坑指南

Oracle rownum与rowid底层原理与实战避坑指南

1. 为什么刚学Oracle的人总在rownum上栽跟头?刚接触Oracle的开发者,十有八九会在rownum上卡住至少三天。我见过某高校数据库课程的期末项目里,A同学用SELECT * FROM emp WHERE rownum > 5想跳过前5条查后面的数据,结果返回空集…

2026/10/13 10:28:04 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →