文章目录
- 对ES的一些疑问
- 问题1:ES相比mysql本身有哪些优势?
- 问题2:哪些场景适合用ES而不是mysql?
- 问题3:mysql逐行扫描,根据过滤条件检查记录中对应字段是否满足要求属于正排索引,根据二叉树索引检索记录的方式属于正排索引还是倒排索引
- 问题4:对于简单数字字段,为什么不像mysql一样使用B+树作为索引
- 一些概念
- 1、倒排索引
- 2、BKD树
在模糊的影响中,ES查询效率高,尤其是最近组内在推慢sql治理,看到有些单张表已经存在索引数量近10个,表中字段确实比较多,一种治理方式是宽表拆分多个表,降低每个表查询的字段,每个表需要创建和维护索引数量也会降低。也在考虑是不是可以将数据同步到ES,部分查询场景走ES,宽表拆分导致数据比较分散,更新和查询起来更麻烦,使用ES数据完整性可以保证,相同数据使用不同的存储介质进行存储,更新和维护相比来说更简单。这里不仅自问,增加mysql从库从库数量,降低查询压力不行吗,同样的数据同步到ES查询,查询效率就会显著提升吗?
对ES的一些疑问
问题1:ES相比mysql本身有哪些优势?
1、ES会在所有字段上创建索引。
首先对于mysql中的数据同步到ES之后,会以JSON对象的形式进行存储,mysql中一行记录对应ES中一个文档。索引字段都会被索引,对于文本和keyword字段会使用进行分词、然后采用建立倒排索引,对于数值、日期等其它类型字段使用不同的数据结构和索引技术,例如对于数值和地理位置数据使用BKD树。
2、水平扩展。
当数据量增加时,可以通过增加结点实现自动水平扩容,而mysql要实现水平扩容,往往需要手动操作,复杂度较大。
3、分布式检索和并行处理。
ES天然将数据分片存储,并行查询时将每个分片上结果合并处理,mysql虽然也支持分库分表,但分库分表全部扫描效率相对较慢。
4、ES支持对文本进行全文检索,比mysql的模糊查询要快。
例如现在有一个用户表,其中包含一个个人简介profile字段,并且该表数据同步一份到了ES,二者要查询喜欢唱歌的人,查询方式分别如下,
对于Mysql,使用的是子字符串匹配算法:
SELECT * FROM users WHERE profile LIKE ‘%唱歌%’;
对于ES,使用倒排索引,显而易见,效率更高:
GET /users/_search
{
“query”: {
“match”: {
“profile”: “唱歌”
}
}
}
问题2:哪些场景适合用ES而不是mysql?
场景 | mysql效率 | ES查询效率 | 优先选择 |
---|---|---|---|
简单数字类型,数量不多 | 高,mysql使用起来更简单,可视化效果更好 | 高,虽然也支持高效查询,感觉不是很有必要,相比mysql更重 | mysql |
简单数字类型,数量很多 | 通过建立索引和分库分表依然可以胜任,但是维护和查询复杂度会增高,水平分库分表可以降低每个表的数据量,垂直分表可以减少单个表字段,提高单表查询效率,跨表查询将变得复杂,mysql写入高,对于实时写入场景要求高场景可以继续使用mysql | 分布式扩展和并行查询,大数量查询效率高,并且天然支持水平扩展,写入效率没有mysql高,对于做聚合分析效率高,一般也会同步一份数据到ES,负责一些非实时的查询 | mysql和ES同时使用 |
包含大文本 | 低,尤其模糊查询 | 高,使用了倒排索引 | ES |
问题3:mysql逐行扫描,根据过滤条件检查记录中对应字段是否满足要求属于正排索引,根据二叉树索引检索记录的方式属于正排索引还是倒排索引
B+树非叶子结点存储记录中某一列的值,叶子结点存储记录的id,倒排索引是根据某个词查询出所在的所有文档列表,二者虽然都是从记录中某个值查询整个记录的信息所在位置(唯一文档标识或者记录逐渐),但是二者一个是查询出一条记录,一个是查询出这个单词出现的所有文档列表,差别还是很大的,一个用于大文本,一个用户非大文本,专门解决的场景也不一样。
问题4:对于简单数字字段,为什么不像mysql一样使用B+树作为索引
首先从ES的定位来说,ES是为了提高多字段联合查询,虽然在多个字段上使用B+树创建联合索引,但是其实是将多个字段顺序化,但其实在相近的数据,在空间上往往距离也很近,对于B+树没有保留数据的空间信息,查询效率不是很高,而是使用使用了保留数据空间特征的BKD-Tree作为索引。
基于B+树创建的联合索引。
如下图所示,创建和查询都是优先表第一列,只有第一列相同才会比较第二列,这样多维数据在逻辑上就变成了一维。
对于BKD树,在创建索引,每层会依次按照k个纬度交替轮流进行划分,这样不用等第一维值全部检索完才能利用后面纬度数据进行数据查找,如下图依次是二维和三维BKD树的的示意图,对于二维BKD树,奇数层次按照第一维度划分,偶数层次按照第二维进行划分,依次交替。
一些概念
1、倒排索引
倒排索引,也成为方向索引,是一种常用在文档检索系统中的索引方法,包含两种形式,第一种,反向文档索引一条记录的水平反向索引,包含每个单词所在文档列表;第二种,完全反向索引一个单词的水平反向索引,包含每个单词在一个文档中位置。三条记录,举例说明,:
T0=“what is banann”
T1= “it is what is it”
T2=“it is a banana”
反向文档索引:
“a” : {2}
“banana”: {0,2}
“is” :{0,1,2}
“it”:{1,2}
“what”:{0,1}
完全反向索引:
“a” : {(2,2)}
“banana”: {(2,3)}
“is” :{(0,1),(1,1),(1,3),(2,1)}
“it”:{(1,0),(1,4),(2,0)}
“what”:{(0,0),()1,2}
比如查询条件为“What”, “is”, “it”,计算每个关键词出现的文档取交集{0,1}∩{0,1,2}∩{1,2}={2},使用完全反向索引同理,只会对文档位置取交集,例子三条记录是正向索引,根据文档id,检索每个文档包含的内容。
2、BKD树
BKD树全称为Block-K-dimension Tree,是多维树(K-dimension Tree,KD-Tree)的改良版本,改善了内存利用率和更好的查询效率,多用于多维数据搜索。