elasticsearch菜鸟教程 阿里云elasticsearch内核介绍( 二 )


Lucene中同时包括行存(Store)与列存(DocValues)的存储方式,但不管是行存还是列存,当应用IndexSorting后,相邻数据的相似度就会越高,也就越利于压缩 。这不仅仅是体现在排序字段上,也体现在其他字段的相似度上 。比如时序场景,当按照时间排序后,各个Metrics的值的近似度也会越大 。所以IndexSorting可以提高数据的压缩率 。
IndexSorting是否适合我的场景?由排序条件决定是否适合
IndexSorting最大的作用就是优化查询性能,其适用的场景就是能够被其优化的场景,比如说:
查询时需要根据某列或者某几列排序后返回的场景:让IndexSorting顺序跟要查询的Sort顺序一致,让Lucene能够提前中断来提升性能 。不关心结果顺序的场景:也可以按照某列IndexSorting,查询时也设置按照这一列Sort即可 。有几种排序需求的场景:IndexSorting起码可以优化一种排序需求,其余的几种需求可以考虑是否多建几个索引,用空间换时间 。也有些场景不能被其优化,比如根据文档相似度分数排序的场景,这时候很难进行预排序,因为相似分数是每次查询时才算出来的 。
根据查询原理看是否能优化
上面提到Lucene会按照docID从小到大的顺序选出符合条件的doc,但是有时查询并不是慢在这个筛选过程,而是构造docID列表的过程,这时IndexSorting带来的优化效果会比较有限 。
因为Lucene的查询原理是比较复杂的,这里只列举两个例子:
对于字符串进行Range查询,且Range范围内有很多符合条件的Term的场景 。这个场景下,查询可能会慢在两个地方,一个是Range范围内符合条件的Term非常多,扫描FST耗时很大,另一个如果这些Term对应的doc数很多,要构造BitSet也会非常耗时 。因为利用IndexSorting的提前中断是发生在BitSet构造好之后,所以并不能优化到这个地方的性能 。对数字类型在BKD-Tree上进行范围查找时,因为BKD-Tree里的docID不是顺序排列的,所以并不像倒排链一样可以顺序读取 。如果BKD-Tree上符合条件的docID很多,构造BitSet也很耗时,也不是IndexSorting能够优化到的 。考虑对写入性能的影响
IndexSorting优化的是查询性能,因为在写入时需要对数据进行排序,所以降低了写性能 。如果写性能是目前的性能瓶颈,或者看重写性能要高于查询性能,那么不适合使用IndexSorting 。
IndexSorting是如何实现的?本文介绍一下IndexSorting的实现细节,这也有助于大家理解它对写入性能产生的影响 。IndexSorting可以保证在每个Segment中,数据都是按照设置的方式进行排序的,这要解决两个问题:
Lucene的Flush操作会生成Segment,这时候生成的Segment如何保证数据有序 。多个Segment进行合并时如何保证有序 。1. Flush时保证Segment内数据有序
大家知道,数据写入Lucene后,并不是立即可查的,要生成Segment之后才能被查到 。为了保证近实时的查询,ES会每隔一秒进行一次Refresh,Refresh就会调用到Lucene的Flush生成新的Segment 。额外说的一点是,Lucene的Flush不同于ES的Flush,ES的Flush保证数据落盘,调用的是Lucene的commit,里面会调用fsync,这里的关系值得额外写一篇文章来说清楚 。
我们需要先知道Flush前数据是一个什么样的状态,才能知道Flush时如何对这些数据排序 。每个doc写入进来之后,按照写入顺序被分配一个docID,然后被IndexingChain处理,依次要对invert index、store fields、doc values和point values进行处理,有些数据会直接写到文件里,主要是store field和term vector,其他的数据会放到memory buffer中 。
在Flush时,首先根据设定的列排序,这个排序可以利用内存中的doc values,排序之后得到老的docID到新docID的映射,因为之前docID是按照写入顺序生成的,现在重排后,生成的是新的排列 。如果排序后与原来顺序完全一致,那么什么都不做,跟之前流程一样进行Flush 。


以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: