番禺网站建设企业,团购网站切换城市js特效代码,青海网站建设公司哪家好,网站建设自学教程1.从全文检索说起
首先介绍一下结构化与非结构化数据#xff1a;
结构化数据将数据具有的特征事先以结构化的形式定义好#xff0c;数据有固定的格式或有限的长度。典型的结构化数据就是传统关系型数据库的表结构#xff0c;数据特征直接体现在表结构的字段上#xff0c;…
1.从全文检索说起
首先介绍一下结构化与非结构化数据
结构化数据将数据具有的特征事先以结构化的形式定义好数据有固定的格式或有限的长度。典型的结构化数据就是传统关系型数据库的表结构数据特征直接体现在表结构的字段上所以根据某一特征做数据检索很直接速度也比较快非结构化数据没有预先定义好的结构化特征也没有固定格式和固定长度。典型的非结构化数据包括文章、图片、视频、网页、邮件等其中像HTML网页这种具有一定格式的文档也称为半结构化数据
对于非结构化的数据检索被称为全文检索。
假设现在MySQL中有一张User表含有三个阶段姓名name、年龄age和爱好favor
对于User表来说整体上是结构化的比如name、age都可以直接建立索引来快速地检索。 而其中的favor字段是一个text类型存储的是非结构化的文本数据 篮球、足球、爱运动的我本人热爱学习游戏偶尔也玩
与结构化查询相比全文检索面临的最大问题就是性能问题。全文检索最一般的应用场景是根据一些关键字查找包含这些关键字的文档比如互联网搜索引擎要实现的功能就是根据一些关键字查找网页。显然如果没有对文档做特别处理查找的办法似乎只能是逐条比对。
假设现在需要找到favor中含有“足球”这个关键字的User那么只能使用like模糊查询 select * from user where favor like %足球%
like语句是无法建立索引的查询时会进行全表扫描并且在每个favor字段中进行遍历匹配以找到含有“足球”这个关键字的记录整体复杂度特别高所以全文检索也是MySQL这类结构关系式数据库无法很好实现的需求。
全文检索一般是查询包含某一或某些关键字记录所以通过文档整体值建立的索引对提高查询速度是没有任何帮助的。为了解决这个问题人们创建了一种新索引方法这种索引方法就是倒排索引。
2.倒排索引的原理
倒排索引是为了解决上述非结构化数据的检索问题而产生的。
首先明确一下在ES中存储记录的单位是JSON“文档”而JSON“文档”中的“字段”也就是组成JSON的一个个KV对。
普通索引也被称为正排索引也就是通过对主键和结构化字段建立索引通过这些结构化索引找到文档。
倒排索引则是先将文档中包含的关键字全部提取出来然后再将关键字与文档的对应关系保存起来最后再对关键字本身做索引排序。用户在检索某一关键字时可以先对关键字的索引进行查找再通过关键字与文档的对应关系找到所在文档。
假设上述的User表通过ES存储其中两个User文档为
{_id: 1,name:pbr1,age:22,favor:篮球、足球、爱运动的我本人热爱学习游戏偶尔也玩
}{_id: 2,name:pbr2,age:22,favor:篮球、足球、爱运动的我
}其中favor定义为text类型假设分词器进行以下分词
文档1的favor分词“篮球”、“足球”、“爱运动的我”、“本人热爱学习”、“游戏偶尔也玩”这5个token文档2的favor分词“篮球”、“足球”、“爱运动的我”这3个token
那么对分词token建立索引并建立对原始文档的映射就得到一个以favor进行分词的倒排索引
可以看到倒排索引实际上就是对全文数据结构化的过程。对于存储在关系型数据库中的数据来说它们依赖于人的预先分析将数据拆解为不同字段所以在数据插入时就已经是结构化的而在全文数据库中文档在插入时还不是结构化的需要应用程序根据规则自动提取关键字并形成关键字与文档之间的结构化对应关系。
比如现在需要查询爱好为“篮球”和“足球”的用户那么可以直接通过倒排索引拿到对应的文档1和文档2也就查询到了这两个用户。
3.ES索引构建过程
全文检索中提取关键字是非常重要的一步。这些预先提取出来的关键字在Elasticsearch及全文检索的相关文献中一般称为词项Term文档的词项提取在Elasticsearch中称为文档分析Analysis是整个全文检索中较为核心的过程。这个过程必须要区分哪些是词项哪些不是。对于英文来说它还必须要知道apple和apples指的同一个东西而run和running指的是同一动作。对于中文来说就更麻烦了因为中文词语不以空格分隔所以面临的第一难题是如何将词语分辨出来。
ES底层使用了Lucene来构建索引一个基本的过程是先对text类型的字段进行分词分词使用的分词器以配置mapping时指定的为准默认使用standard分词器对于中文分词来说一般建议使用ik_smart或ik_max_word分词器 关于Lucene如何存储这些分词解析结果可以学习这篇文章https://www.shenyanchao.cn/blog/2018/12/04/lucene-index-files/
由于文档存储前的分析和索引过程比较耗资源所以为了提升性能文档在添加到ES中时并不会立即被编入索引。
默认情况下ES会每隔1s统一处理一次新加入的文档可以通过index.refresh_interval参数修改。
为了提升性能在ES 7中还添加了index.search.idle.after参数它的默认值是30s如果索引在一段时间内没有收到检索数据的请求那么它至少要等30s后才会刷新索引数据。
所以可以看出ES的写入操作实际上是准实时的新添加到索引中的文档可能在一段时间内不能被检索到如果的确需要立即检索到文档可以使用强制刷新到索引的方式包括使用_refresh接口和在操作文档时使用refresh参数等进行强制刷新缓冲区中的索引到磁盘中。