特别加餐 | 高性能检索系统中的设计漫谈
陈东
该思维导图由 AI 生成,仅供参考
你好,我是陈东。欢迎来到检索专栏的第三次加餐时间。
在进阶篇的讲解过程中,我们经常会提起一些设计思想,包括索引与数据分离、减少磁盘 IO、读写分离和分层处理等方案。这些设计思想看似很简单,但是应用非常广泛,在许多复杂的高性能系统中,我们都能看到类似的设计和实现。不过,前面我们并没有深入来讲,你可能理解得还不是很透彻。
所以,今天我会把专栏中出现过的相关案例进行汇总和对比,再结合相应的案例扩展,以及进一步的分析讨论,来帮助你更好地理解这些设计思想的本质。并且,我还会总结出一些可以参考的通用经验,让你能更好地设计和实现自己的高性能检索系统。
设计思想一:索引与数据分离
我要说的第一个设计思想就是索引与数据分离。索引与数据分离是一种解耦的设计思想,它能帮助我们更好地聚焦在索引的优化上。
比如说,对于无法完全加载到内存中的数据,对它进行索引和数据分离之后,我们就可以利用内存的高性能来加速索引的访问了。第 6 讲中的线性索引的设计,以及 B+ 树中区分中间节点和叶子节点的设计,就都使用了索引和数据分离的设计思想。
那如果索引和数据都可以加载在内存中了,我们还需要使用索引和数据分离吗?在这种情况下,将索引和数据分离,我们依然可以提高检索效率。以第 5 讲中查找唐诗的场景为例,我们将所有的唐诗存在一个正排索引中,然后以关键词为 Key 建立倒排索引。倒排索引中只会记录唐诗的 ID,不会记录每首唐诗的内容。这样做会有以下 3 个优点。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了高性能检索系统设计中的关键设计思想,包括索引与数据分离、减少磁盘IO、读写分离以及分层处理。首先,索引与数据分离能够帮助系统聚焦于索引的优化,提高检索效率,但需要注意数据一致性。其次,减少磁盘IO是保证系统高性能的核心设计思路,包括将数据加载到内存中、使用压缩索引、顺序写大批量数据等技术手段。读写分离的设计方案可以大幅度提升系统的性能,如MySQL的Master - Slave架构。分层处理也是重要的设计思路,将核心资源用来处理核心数据,提升整体系统性能。这些设计思想虽然简单,但几乎无处不在,对于设计和实现高性能检索系统具有重要指导意义。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《检索技术核心 20 讲》,新⼈⾸单¥59
《检索技术核心 20 讲》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(4)
- 最新
- 精选
- 奕非聚集索引。如果要保证 MyISAM 的数据一致性,那我们需要在表级别上进行加锁处理。 -------------------- 为什么 非聚集索引 即叶子节点保存的是指针,就不能有行级别的锁呢? 我保证指针指向的记录不能更新不就可以了吗?
作者回复: 这是因为MySQL的锁机制是在引擎层实现,而不是是数据层实现。因此,行锁是加在索引上。oracle倒是把行锁加在了数据行上。
2020-05-086 - 那时刻对于老师总结的这几部分,我的想法如下,不恰当的地方,烦请老师指正。 1. 索引和数据分离 我想到了存储计算分离的设计,比如消息队列Pulsar就是采用这样设计,存储消息的职责从Broker分离出来,交给专门存储集群,这样Broker就变成无状态的节点,灵活的集群调度。Bigquery和aws Aurora也是如此的设计。 2. 减少磁盘 IO Kafka中通过分批,顺序读写IO,也使用Zero Copy加快数据读取速度 3. 读写分离 服务器在操作数据库的时候,采用读写分离,降低服务器的压力,但是得注意数据最终一致性问题。 4. 分层处理 在服务器和数据库中间加入Redis作为缓存,可以看做一种分层处理,来缓解直接访问数据库的压力。在ES里把数据分为冷热数据也有类似的思想。
作者回复: 总结得挺好的~ 对于你提到的例子,在数据库和服务器间加入一个缓存层的设计,其实也是非常常见的例子,无论是使用memcached,还是Redis的案例都有。 不过,分层处理和减少磁盘IO在某些场景下会有重叠。在我看来,单纯使用一个缓存层加载全部数据的话,我会将它归在“减少磁盘IO”中。但是如果是“将部分最热的数据装载到缓存中”,那么就是应用了二八原则的分层处理思想。
2020-05-041 - 峰1. 索引和数据分离 老师讲到的mysiam和innodb的例子,我觉得有点怪,因为数据操作影响到的数据结构全局还是局部,才是加锁范围的核心因素。这里我并没有看到直接联系,除非说mysiam的真实数据就在磁盘里连续存成了一个数组,但还是和数据索引分离不分离没啥子关系。 而且其实我认为innodb这样的也算数据索引分离,毕竟索引页和数据页是分离的。我能想到的好像都是数据索引分离的机构,OLAP各种列存结构(数据按列分块存,并在基础上额外加一些minmax,skipindex等一些索引), 以及LSM为代表的一众TP数据库,像hbase中hfile数据块索引块,当然我隐约感觉磁盘存储的话索引数据不分离,有很大的复杂度,还想不太明白,不胡说八道了。 2. 减少磁盘 IO 老师讲的有的有点多啊,比较快想到的不一样的是各种编码的算法,hbase diff以及列存的delta dictionaryencoding等等。 3. 读写分离 读写分裂更广泛的含义在于把不同的workload的任务相互分开,使得不会相互影响。 实时数仓(Druid,pinot,以及阿里的adb)就一般采用lambda架构,把实时摄入的分一波,历史节点的数据分一波,实时摄入完了,数据迁移到历史节点。 4. 分层处理 说道分层处理,我就觉得国内不管教学也好,还是实际工作中也好,就通常比较聚焦在没一层的东东上。比如说数据库,我们会讲内存中长啥样,磁盘中讲啥样,问题是disk-base的数据库存储侧比较重要的一点在于怎么让数据尽可能的move 到上层的存储器,同时满足事务等约束,所以数据在各个层次之间的movement我就很少可看到人讲,学的时候老感觉缺一块。o(* ̄︶ ̄*)o,扯回主题,时序数据库就很抢到数据的分层结构,毕竟数据本身的特性——最近的数据越有价值摆在这里,所以一般都会按时间进行切片,不同的切片去灵活部署到不同的dataserver或者采用不同的数据结构。
作者回复: 1.的确,一般来说,我们是对数据进行加锁,但innodb是对索引加锁,而不是对记录加锁。这也是理解innosb特点的关键。有兴趣可以深入研究一下。 4.你说到了很好的一个点:数据在不同层之间是怎么移动的?这个的确也很重要。我下一篇正好就会讲到一个内存数据往磁盘写的例子,敬请期待。
2020-05-06 - ifelse学习打卡2023-04-17归属地:浙江
收起评论