摘要:ES已经成为了全能型的数据产品,在不少领域愈来愈受欢迎,本文旨在从数据库领域分析ES的使用。
本文分享自华为云社区《Elasticsearch数据库加速实践》,原文做者:css_blog 。css
1、方案说明
Elasticsearch主要功能是什么,不一样的场景有不一样的定位,在日志场景咱们能够用ELK生态搭建日志分析系统,在搜索领域ES是当前最热门的搜索引擎。在大数据领域,ES能够对标Hbase提供海量日志的数据仓库;在数据库领域ES能够做为查询分析型的分析型数据库使用。ES已经成为了全能型的数据产品,在不少领域愈来愈受欢迎,本文旨在从数据库领域分析ES的使用。sql
ES不是关系型数据库,数据更新采用乐观锁,经过版本号控制,不支持事务处理,这也是ES区别于传统数据库(Mysql)的地方;可是ES支持精确查询加速,多条件任意组合查询,多种聚合查询,查询速度很快,能够替代数据库复杂条件查询的场景需求,甚至能够代替数据库作二级索引。数据库
在数据库加速场景一般的作法是客户产生的商品订单数据会写入Mysql类关系型数据库,数据库写入保证事务性,可是随着商品订单的数据愈来愈多,同时客户查询的条件多变,没法全部字段都创建索引,数据库的查询能力远远不能知足查询诉求。咱们考虑用ES全量同步数据库数据,在ES中作多条件聚合查询,查询的结果能够在Mysql中作关联搜索,在查询商品订单详情展现, Mysql数据和ES数据能够不要求实时一致,能够通canal消费Mysql binlog日志信息, 同步到ES,实现一次写入,保证数据一致性。如下数据库都以Mysql为例进行说明。网络
2、索引原理分析
ES为何查询能力远远超过Mysql关系型数据库,主要是他们的实现原理和底层存储的数据结构差别决定的,如下比较两种产品的实现原理。数据结构
Elasticsearch会对全部输入的文本进行处理,创建索引放入内存中,从而提升搜索效率。在这一点上ES要优于MySQL的B+树的结构,MySQL须要将索引放入磁盘,每次读取须要先从磁盘读取索引而后寻找对应的数据节点,可是ES可以直接在内存中就找到目标文档对应的大体位置,最大化提升效率。而且在进行组合查询的时候MySQL的劣势更加明显,它不支持复杂的组合查询好比聚合操做,即便要组合查询也要事先建好索引,可是ES就能够完成这种复杂的操做,默认每一个字段都是有索引的,在查询的时候能够各类互相组合。架构
(1)数据库索引B+树
数据库中索引都是以树来组织的,经常使用的有B tree,B-tree,B+tree,如下介绍B+tree的组织结构。并发
首先咱们先想象下为何须要创建索引,假设咱们有一张表book,存储了咱们保持的书籍信息,名称,做者,发布时间等,咱们有10000条记录,若是咱们须要找一本为《database》的书,那咱们的SQL为:app
select name,author form book where name = ‘database’;
咱们须要扫描整个表,全量比较才能够,若是咱们对name创建索引,书名已经按照顺序排序,查询时只须要找到对应位置就能够快速获取结果。分布式
索引的本质是经过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,咱们能够老是用同一种查找方式来锁定数据。性能
数据库采用B+tree创建索引:
B+tree 数据只存储在叶子节点中。这样在B树的基础上每一个节点存储的关键字数更多,树的层级更少因此查询数据更快,全部指关键字指针都存在叶子节点,因此每次查找的次数都相同因此查询速度更稳定。
(2)Elasticsearch索引原理
ES创建索引采用倒排索引的方式存储。
对输入的全部数据都创建索引,而且把全部和文档对应起来,在咱们查找数据的时候咱们直接查找词典(Term),在找到Term对应的文档ID,进而找到数据。这和Mysql使用B+tree树创建索引的方式相似,可是若是词典Term很大,对Term的搜索就会很慢,ES进一步建议了词典索引(FST),提高词典的搜索能力。
Term Index 以树的形式保存在内存中,运用了FST+压缩公共前缀方法极大的节省了内存,经过Term Index查询到Term Dictionary所在的block再去磁盘上找term减小了IO次数。
Term Dictionary 排序后经过二分法将检索的时间复杂度从原来N下降为logN。
3、查询对比分析
如下对于数据库搜索经常使用的场景对比ES和数据库:
- 全文检索
ES支持全文检索,能够对数据分词,每一个词经过FSP创建词典索引,而Mysql关系数据库则不支持,想象下若是搜索的不是整个字段而是字段中的几个关键词,使用Mysql搜索必须全表扫描。
- 精确搜索
若是Mysql对该字段创建过索引,使用ES搜索和Mysql搜索性能差别不大,可能Mysql更快点,可是ES是分布式系统,能够支持PB级别的数据搜索,对大表搜索ES优点更明显。
- 多条件查询
咱们知道Mysql须要对字段创建索引才能加速搜索过程,而ES默认是全索引的,对于多条件查询,触发Mysql创建联合索引,不然多个字段搜索,Mysql 先选择一个字段搜索,结果在使用第二个字段过滤获得最终结果。
ES则采用多个字段结果集交并操做,使用bitmap或者skiplist加快搜索速度,相比Mysql优点明显。
- 聚合搜索
Mysql聚合搜索若是没有创建索引须要全表扫描排序,若是创建索引在B+tree上进行范围查询。
ES为了加快聚合搜索速度,经过Doc value来解决聚合搜索问题。DocValue就是列式存储。
存储结果以下:
Docvalue数据按照文档ID排序,DocValue将随机读取变成了顺序读取,
在es中,由于分片的存在,数据被拆分红多份,放在不一样机器上。可是给用户体验却好像只有一个库同样。对于聚合查询,其处理是分两阶段完成的:
- Shard 本地的 Lucene Index 并行计算出局部的聚合结果。
- 收到全部的 Shard 的局部聚合结果,聚合出最终的聚合结果。
这种两阶段聚合的架构使得每一个 shard 不用把原数据返回,而只用返回数据量小得多的聚合结果。这样极大的减小了网络带宽的消耗。
- 多副本加速
咱们知道ES有shard和replica的概念,副本一方面能够保证数据的可靠性,另外一方面多副本能够加快搜索速度提升搜索并发能力。
4、数据库到Elasticsearch同步方案
结合用户实际的使用方式和数据量的大小,Mysql数据到ES能够有多种不一样的方式选择。
- Canal=>Elasticsearch
使用Canal直接消费Mysql binlog日志写入ES,这种方式若是Mysql写入量大,会面临Canal写入阻塞问题。
- Canal =>Kafka=>Elasticsearch
Canal数据写入到Kafka,使用另外的app消费Kafka数据同步到ES
5、问题汇总
1.索引shard问题
在Mysql数据同步到ES中面临索引的创建的问题,在数据写入ES以前咱们须要提早规划数据的shards和replicas的个数,replicas 能够动态修改,可是shards数建立完成后不能修改。
随着Mysql数据量的增长,若是shard太少,就会致使每一个shard的数据量太大的问题。
若是一个索引600G,只有3 个shard,每一个shard就200G,会极大的损耗查询能力,也不利于数据迁移。
咱们能够按照月来滚动建立索引,经过索引别名把全部索引关联起来使用。
test_data-202101 test_data-202102
2.查询加速问题
在使用ES对数据库进行加速的场景,咱们但愿的是ES查询能力尽量快。在ES查询不知足要求的时候咱们须要对查询进行调优。
经常使用的方法有: