- query和filter的区别
filter是直接过滤掉,没有分数;(都是结构化数据)(查询上下文)
query会涉及匹配相似度打分,_score说明文档匹配度,(过滤上下文)
term直接去查倒排索引,效率最高。
2.bulk/mget批量请求
一次请求多个操作,减少了频繁反复的网络请求,必然提高了索引速度。
一次把请求加载到内存,用指定的格式请求,减少了内存占用;
请求中的每个操作都是独立的,依次解析通过路由转发到对应的主节点上,并行执行操作;然后再同步到对应的副本分片上,索引效率也必然提高了。
3.搜索-es搜索的强大之处
结构化搜索:有些字段可以使用结构化搜索(年龄、性别等),日期可以用来排序;
全文搜索:可以找出所有匹配关键字的文档,并排序返回。
mapping(映射):数据在字段中如何存储;
analysis(分析):数据如何处理,已被更好的检索到。(分词、标准化过程)(字符过滤器 -> 分词器 -> token过滤器(小写化,停用词,同义词,词干提取)) index属性控制怎么索引字符串(analyzed/not analyzed(就是映射为一个精确值))
query dsl(特定领域的查询语言): es的查询语言。
4.elasticsearch中的数据,分为精确值和全文,两大类型
精确值:就是非常精确的,如:日期、用户名、用户id和邮箱。都是结构化数据。精确值很容易查询,结果二值化,要么匹配要么不匹配。
全文:指文本数据,人类容易识别的语言书写,如邮件内容、推文内容。通常是非结构化数据,都是自然语言,规则复杂,计算机难以理解。
全文类型不会做精确匹配,只会在全文域中做搜索,并且能理解搜索意图。(因此,我们需要对全文类型的数据做文档分析,然后建立倒排索引)
对搜索字符串、全文域中的内容,做同样的标准化规则处理。(才能保证搜索到想要的内容)
检索语句:分 查询 和 过滤 两种检索形式。。
过滤filter:不评分,二值的结果。
查询:会评分,匹配的多好,这种相关性概念很适合全文搜索,因为全文搜索没有正确答案,
查询操作拥有变成不评分的能力,单独的query指scoring query
filters模块被移除了,只保留filter(表示不评分、只过滤的查询)
过滤查询:计算很快,结果会被缓存,(filter query)
评分查询:不仅要找出匹配的文档,还要计算相关性,结果不会缓存,相关性计算很费力。
倒排索引(inverted index): 使得评分查询性能表现良好,但是整体上来看,过滤查询的性能更高,更稳定。
过滤的目标:减少评分查询检查的文档个数。。
应用场景:全文搜索或者需要相关性分数的评分查询。 其余都尽量用过滤。。
should: 满足这些语句,将增加修正性得分,不满足也没事。
bool用来汇总每个子句的得分。
同一个字符串字段,可以用两种方式进行索引,比如analyzed用于搜索,not_analyzed用于排序。fields字段用于mapping。
es中的相关性:全文本字段的值相对于全文本检索词相似程度的算法。TF/IDF,
检索词频率:检索词在字段出现的频率,频率越高,相关性越高,
反向文档频率:检索词在索引中出现的频率,频率越高,相关性越低,在大多数文档中都出现的词,则权重更低。
字段长度准则:字段越长,相关性越低。
倒排索引检索很快,(搜索时可以通过搜索关键词快速得到结果集)
但是字段值排序的性能却不是很理想。(排序时,需要某个字段值的集合,要转置倒排索引)列存储。
Doc Values就是一种列存储。索引时创建字段的Doc Values。 Doc Values用于字段排序、字段聚合、地理位置过滤,等等。(索引时创建的平行数据结构,排序的关键结构)用内存和页缓存,使得读写更高效。
搜索和CRUD不同,CRUD只是对单个文档进行操作,路由唯一确定,对单个分片操作即可。
搜索需要一个更加复杂的执行模型,不确定命中哪些文档。搜索分为两个阶段: query then fetch.
query:
1.请求发送到协调节点,协调节点自己创建一个优先队列(协调节点广播查询请求到所有相关分片,并将它们的响应整合成全局排序的结果集合。)
2.协调节点广播请求到集群中每个节点的分片拷贝,查询请求可以被某个主分片或副本分片处理。
3.每个分片在本地执行查询请求,并创建from+size的优先队列,
4.分片返回一个轻量级的查询结果列表(仅包含文档id和排序需要的值)给协调节点;
5.协调节点将分片级的结果汇总到自己的优先队列中,代表全局排序结果集合,至此查询结束。
fetch:
1.协调节点辨别哪些文档需要被取回,并向相关分片提交GET请求;
2.每个分片加载并丰富文档,返回给协调节点。
3.每个文档都被取回了,则返回给客户端。
搜索耗时 = 最慢分片的处理时间 + 协调节点合并时间(一个节点有问题,就会导致所有响应缓慢)
游标查询 scroll
深度分页的代价在于结果集全局排序。
避免深度分页,有效执行大批量的文档查询,游标查询用字段_doc排序,让es仅仅从还有结果的分片返回下一批结果。
启动游标查询时,设置参数scroll值为我们期望的游标查询的过期时间(相当于一个时间窗口,在这时间段内系统会缓存消耗资源,时间过后系统会考虑释放掉占用的资源),每个批次通过scroll_id保持同步,前后连续起来。
分片内部原理1.倒排索引:
倒排索引保存每一个词项出现过的文档总数,对应文档中一个词项出现过的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度,这些信息可以决定相关性顺序,要提前知道集合中的所有文档。
倒排索引写入磁盘后,是不可改变的。(所以,不需要锁; 索引会缓存,读请求直接读内存,比起读磁盘,性能大大提升;filter缓存也很方便,不变的;要修改的话,就要重建索引)
动态更新索引:
保持索引不变性,增加新的补充索引来反映新近的修改,每一个倒排索引都会被轮流查询到,查询完后再对结果合并。
ES基于Lucene,引入按段搜索(Segment)的概念. 每一段本身都是一个倒排索引。索引本身就是所有段(segment)的集合,
提交点(commit):一个个列出所有已知段的文件。
逐段搜索(segment):
1.新文档被收集到内存索引缓存;
2.不时地,缓存被提交:
一个新的段,一个追加的倒排索引,被写入磁盘;
一个新的包含新段名字的提交点,被写入磁盘;
磁盘进行同步-所有在文件系统缓存中等待的写入都刷新到磁盘,以确保它们被写入到物理文件。
3.新的段被开启,让它包含的文档可见已被搜索;
4.内存缓存被清空,等待接收新的文档。
当一个查询被触发,所有已知的段按顺序被查询。词项统计会对所有段的结果进行聚合,以保证每个词和每个文档的关联都被准确计算。用相对较低的成本将新文档添加到索引。
删除:提交点提交一个.del文件,文件列出被删除的段信息。
文档更新:文档新版本被索引到一个新的段中。
磁盘成了性能的瓶颈,还不够快。
提交一个新的段到磁盘,需要一个从缓存同步操作,确保断电不会丢失数据。但同步代价很大。
Lucene允许新段被写入和打开,使其包含的文档在未进行完整提交时便对搜索可见。比进行提交代价小得多,还可以频繁执行。
写入打开轻量的过程叫refresh,分片默认一秒自动刷新一次,近实时,一秒可见。
为了数据可靠,必须做持久化变更,translog(事务日志)。缓存被清空,translog不会,会继续记录,
每隔一段时间,flush,索引全量刷新,translog被删除,生成新的translog。
自动刷新,创建新的段,会很耗性能,还会轮流检查段,更慢。。
后台进行段合并,索引和搜索时,段合并操作自动进行。
大数据规模的聚合,提供了cardinality 和 percentiles 两种算法来实现近似聚合,估算的方式。高速的执行效率,极小的内存消耗。
cardinality (注:基数)度量。 它提供一个字段的基数,即该字段的 distinct 或者 unique 值的数目



