说在前面mysql
财务平台进行分录分表之后,随着数据量的日渐递增,业务人员对帐务数据的实时分析响应时间愈来愈长,体验性慢慢降低,以前咱们基于mysql的性能优化作了一遍,能够说基于mysql该作的优化已经基本上都作了,本次是基于elasticsearch对其作进一步的性能优化算法
正文sql
mysql索引原理数据库
基于mysql最经常使用也最直接有效的性能优化也就是添加索引。json
mysql索引是怎么实现的呢?数据库最基本的查询算法是顺序查找,时间复杂度为O(n),显然在数据量很大的时候很低,优化的查询算法有二分查找,二叉树查找,虽然查找效率提升了,可是各自对检索的数据都有要求,二分查找检索被要求数据是有序的,而二叉树查找只能用于二叉树上,可是数据自己的组织结构不可能彻底知足各类数据结构,例如,理论上不可能同时将两列都按顺序进行组织,因此在数据以外,数据库系统还维护者知足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就能够在这些数据结构上实现高级查找算法,这种数据结构就是索引。数组
索引是什么?索引是存储引擎用于快速找到记录的一种数据结构,这是索引的基本功能,主要基于hash,b+tree。缓存
咱们开发当中通常用到都是mysql innoDB引擎,采用的是b+tree。性能优化
b+tree的优点主要体如今查询性能上,在单元素查询时,b+tree会自顶层向下逐层查找节点,最终找到咱们须要的叶子节点,范围查询时,b+tree找到叶子节点的起始位置,经过叶子节点链表依次查询数据,直到范围结束为止。服务器
参考上面的示意图数据结构
总结:基于b+tree的mysql索引,当这个树的形状瘦低的时候查询效率就会很快,由于查找磁盘的io次数不多,可是若是这个树的形状胖高的时候,查询磁盘的次数就会比较多,那么查询效率就会愈来愈慢,因此基于mysql索引的性能优化,索引是有限制的,适量的添加索引会对查询效率有明显提高,可是索引过量就拔苗助长,不但查询效率会下降,也会影响其余操做的效率,由于其余操做的时候也是须要维护索引的。
elasticsearch索引原理
elasticsearch底层是索引原理是倒排索引,使用场景通常是OLAP,支持rest风格json数据格式交互的全文检索引擎,开源,面向文档设计,实时检索,索引能够无限扩展,只要你的服务器的磁盘、内存足够大。
咱们先看一个列子
一个字段有一个本身的倒排索引。18,20这些叫作term,而[1,3]就是postinglist。Posting list就是一个int的数组,存储了全部符合某个term的文档id。
term Dictionary
term排序后的集合,方便二分查找,有了term Dictionary以后就能够在磁盘上查找到具体的document,磁盘的读操做很是昂贵,一次大概须要10ms时间,不一样存储方式的磁盘性能不同,因此为了减小磁盘的读取次数就必要把一些数据缓存到内存中,可是term Dictionary会有不少,不能完整的放到内存中,因而就有了termindex
term index
能够理解为就是英文词典的目录,它是一棵树的结构
示意图
这棵树不会包含全部的term,它只包含term的一些前缀,经过term index能够快速地定位到term dictionary的某个offset,而后从这个位置再日后顺序查找,大大减小了磁盘访问次数
示意图
因此term index不须要存下全部的term,而仅仅是他们的一些前缀与Term Dictionary的block之间的映射关系,再结合FST(Finite StateTransducers)的压缩技术,可使term index缓存到内存中
为何elasticsearch比mysql快
mysql只有 termdictionary这一层,是以树的方式存储在磁盘上的。检索一个term须要若干次的磁盘访问操做,而elasticsearch,在term dictionary的基础上添加了term index来加速检索,term index以树的形式缓存在内存中。从term index查到对应的term dictionary的block位置以后,再去磁盘上找term,大大减小了磁盘的访问次数。
term index在内存中是以FST的形式保存的,其特色是很是节省内存。Term dictionary在磁盘上是以分block的方式保存的,一个block内部利用公共前缀压缩,好比都是Ab开头的单词就能够把Ab省去。这样term dictionary能够更节约磁盘空间。
压缩技术
用FST压缩term index以外,对posting list也有压缩。
联合索引查询
以上都是单field索引,若是多个field索引的联合查询,好比查询age=18 AND gender=女,倒排索引如何知足快速查询的要求呢?大体过程以下:根据过滤条件 age=18 的先从term index找到18在term dictionary的大概位置,而后再从term dictionary里精确地找到18这个term,而后获得一个posting list或者一个指向posting list位置的指针。而后再查询gender=女的过程也是相似的。最后得出age=18 AND gender=女,就是把两个 posting list作一个“与”的合并
一、skip list
二、bitset 二进制,直接按位与
总结
elasticsearch就是尽可能将磁盘里的东西搬进内存,减小磁盘随机读取次数(同时也利用磁盘顺序读特性),结合各类压缩算法,高效使用内存,从而达到快速搜索的目的。
mysql索引与elasticsearch索引对比
mysql
若是数据量不是特别大,在千万级别,适当的管理好索引,查询效率仍是能够的,可是对索引命中率有要求,就是必需要保证索引的命中率,还有就是索引的数量限制好,可是查询条件比较多、须要添加不少索引的时候mysql索引就有瓶颈了。
elasticsearch
使用了OLAP场景,海量数据实时查询,亿级以上数据量,由于底层采用的是倒排索引机制,只要你的服务器资源足够好,理论上随着数据量的增长、索引的增量,实时查询效率是线性的。
说到最后
本次解析仅表明我的看法,仅供参考。