最近和一些大牛在一些聊天时(资深技术专家),想到有必要写这个系列和大家分享点自己的感悟和想法。技术分为快餐技术和慢技术,快餐技术就是大家一看就懂的技术,而且马上就可以使用,看到效果,一般大家都比较喜欢学这个,它的好处是市场需要、快速上手、容易看到结果,不足之处是门槛低,大家都容易掌握,要想提升竞争力比较难;另一种是慢技术,它是需要你花上几个月,甚至一年的时间去消化,它代表了底层的技术,很长时间不会变,学习好它,不仅懂得用,而且知道内部的原理。所以就想到写这个序列,分享自己的一点感想,今天聊的是IO和磁盘中的数据查找,索引话题。
1、计算机处理速度的不相等性
相信这个观点,对于学过计算机的人来讲,并不陌生,很明显计算机处理速度的变慢序列是:cache > 内存 > 磁盘,它们不是在一个层级上。为了提升速度,就引入了缓存(cache),cache是一种高速缓存技术,所以整个计算机体系结构中的一些设计思想,是值得我们去认真学习的,现在很多的技术思想基本上可以在计算机体系结构中找到相似的设计思想,缓存就是其中的一个。为了加快速数据处理速度,尽量把数据放在内存中,避免频繁的读写磁盘。
结论:
内存的处理速度明显快于磁盘
尽量把数据放在内存中,减少磁盘的读写
2、内存和磁盘中查找数据的过程
2.1、内存查找数据
回想一下查找数据的方法有哪些呢?
顺序扫描:从头到尾扫描一个数组,缺点是时间复杂度比较高,是O(N)
二分查找:二分查找的思想是针对一个有序的数组,每次可以折半查找,这样查找一个数据可以节省一半的时间复杂度;
排序树:二分查找是一种折半的查找,很容易看到不断的折半就形成了一棵树,后面就人研究树型结构对于查询的作用,随着研究的深入,发现排序树有时会偏向一方,就发明了平衡排序树,平衡排序树有严格的要求,左右子树的高度不能过1,每次插入的过程中可能会产生旋转,这也是消耗性能的,又发明了红黑树,红黑树是在排序树和平衡排序树中找到一个平衡点,两边的高度差没有平衡排序树那么严格(旋转减少);
Hash法,通过散列的方法来查找,它的时间复杂度是O(1)
结论:
可以看出在内存中,最快的查找是Hash法,通过key就可以查找出value
需求是推动技术不断向前发展(应用场景),如上面的排序树 -> 平衡排序树 -> 红黑树 .....
2.2、 磁盘查找数据
读磁盘数据时,它要经历三个阶段:寻道、磁盘旋转、读写传输,整个最消耗时间的地方是寻道、磁盘旋转,它占整个读写全部时间的90%以上,所以要提升数据,就要减少IO交互,如想到的一些方法如预读,每次读的时间就读一个磁盘块的数据,根据数据相关性,很可能下次要读的数据(不是刚才查的数据,与刚才查找的数据在同一个数据块里),在写数据时,尽量要做到顺序写,不要随机写。
结论:
磁盘读写最花时间的地方是寻道和磁盘旋转,所以要尽量减少IO交互
尽量做到顺序写,不要随机写
3、数据库索引的那些事
问题:为什么数据库的索引要使用B+树呢?
索引可以看作是一个元数据,是数据的数据,目的是为了提升查找数据的速度,如目录一样。那为什么要使用B+树作为索引的数据结构呢,上面不是说hash才是最快的吗?
到这里,要清楚一个问题,索引数据不仅要能快速查找,而且要便于持久化存储,所以基于这个考虑,hash是适合内存查找,不适合磁盘。上面提到,磁盘查找数据的代价是很大的,如果伤痛在所难免,就要减少伤痛,所以减少磁盘IO的次数是关键,如何应对千万级别数据量的查找,不管是数百条记录,还是亿级记录,查找花的时间相近,这就对数据结构有相当大的要求了。B+树的高度就是IO的交互次数,一般B+树是m路树,这个m值很大,在100以上,所以根据计算,百万级别的数据量的查找,其实使用3次IO查寻就行了,其中根节点是常驻内存的,所以只需要2次IO查寻就ok了,这种查找方法是不是很快呢。
结论:
B+树适用于磁盘存储,应对百万级别数据查询,只需要2次IO查询就行了
4、总结
索引在平时工作中,经常遇到,知道它底层的原理思想,有利于知道根据原因,从学习中总结方法论,找到主要矛盾,解决问题。