10大高性能开发宝石,我要消灭一半程序员( 四 )


聚集索引的叶子节点直接存储了数据,也是数据节点,而非聚集索引的叶子节点没有存储实际的数据,需要二次查询 。
索引的实现原理
索引的实现主要有三种:

  • B+树
  • 哈希表
  • 位图
其中,B+树用的最多,其特点是树的节点众多,相较于二叉树,这是一棵多叉树,是一个扁平的胖树,减少树的深度有利于减少磁盘I/O次数,适宜数据库的存储特点 。
10大高性能开发宝石,我要消灭一半程序员

文章插图
 
哈希表实现的索引也叫散列索引,通过哈希函数来实现数据的定位 。哈希算法的特点是速度快,常数阶的时间复杂度,但缺点是只适合准确匹配,不适合模糊匹配和范围搜索 。
10大高性能开发宝石,我要消灭一半程序员

文章插图
 
位图索引相对就少见了 。想象这么一个场景,如果某个字段的取值只有有限的少数几种可能,比如性别、省份、血型等等,针对这样的字段如果用B+树作为索引的话会出现什么情况?会出现大量索引值相同的叶子节点,这实际上是一种存储浪费 。
位图索引正是基于这一点进行优化,针对字段取值只有少量有限项,数据表中该列字段出现大量重复时,就是位图索引一展身手的时机 。
所谓位图,就是Bitmap,其基本思想是对该字段每一个取值建立一个二进制位图来标记数据表的每一条记录的该列字段是否是对应取值 。
10大高性能开发宝石,我要消灭一半程序员

文章插图
 
索引虽好,但也不可滥用,一方面索引最终是要存储到磁盘上的,无疑会增加存储开销 。另外更重要的是,数据表的增删操作一般会伴随对索引的更新,因此对数据库的写入速度也是会有一定影响 。
你的网站现在访问量越来越大了,同时在线人数大大增长 。然而,大量用户的请求带来了后端程序对数据库大量的访问 。渐渐的,数据库的瓶颈开始出现,无法再支持日益增长的用户量 。老板再一次给你下达了性能提升的任务 。
缓存技术 && 布隆过滤器
从物理CPU对内存数据的缓存到浏览器对网页内容的缓存,缓存技术遍布于计算机世界的每一个角落 。
面对当前出现的数据库瓶颈,同样可以用缓存技术来解决 。
每次访问数据库都需要数据库进行查表(当然,数据库自身也有优化措施),反映到底层就是进行一次或多次的磁盘I/O,但凡涉及I/O的就会慢下来 。如果是一些频繁用到但又不会经常变化的数据,何不将其缓存在内存中,不必每一次都要找数据库要,从而减轻对数据库对压力呢?
10大高性能开发宝石,我要消灭一半程序员

文章插图
 
有需求就有市场,有市场就会有产品,以memcached和redis为代表的内存对象缓存系统应运而生 。
缓存系统有三个著名的问题:
  • 缓存穿透: 缓存设立的目的是为了一定层面上截获到数据库存储层的请求 。穿透的意思就在于这个截获没有成功,请求最终还是去到了数据库,缓存没有产生应有的价值 。
  • 缓存击穿: 如果把缓存理解成一面挡在数据库面前的墙壁,为数据库“抵御”查询请求,所谓击穿,就是在这面墙壁上打出了一个洞 。一般发生在某个热点数据缓存到期,而此时针对该数据的大量查询请求来临,大家一股脑的怼到了数据库 。
  • 缓存雪崩: 理解了击穿,那雪崩就更好理解了 。俗话说得好,击穿是一个人的雪崩,雪崩是一群人的击穿 。如果缓存这堵墙上处处都是洞,那这面墙还如何屹立?吃枣药丸 。
关于这三个问题的更详细阐述,推荐一篇文章什么是缓存系统的三座大山 。
有了缓存系统,我们就可以在向数据库请求之前,先询问缓存系统是否有我们需要的数据,如果有且满足需要,我们就可以省去一次数据库的查询,如果没有,我们再向数据库请求 。
注意,这里有一个关键的问题,如何判断我们要的数据是不是在缓存系统中呢?
进一步,我们把这个问题抽象出来:如何快速判断一个数据量很大的集合中是否包含我们指定的数据?
10大高性能开发宝石,我要消灭一半程序员

文章插图
 
这个时候,就是布隆过滤器大显身手的时候了,它就是为了解决这个问题而诞生的 。那布隆过滤器是如何解决这个问题的呢?
先回到上面的问题中来,这其实是一个查找问题,对于查找问题,最常用的解决方案是搜索树和哈希表两种方案 。


推荐阅读