通过对Elasticsearch深入理解(三)—— ElasticSearch是如何做到快速索引的(倒排索引原理)_Mr.二狗的博客-CSDN博客_elasticsearch倒排索引技术实现的阅读,我们可以得知:倒排索引里的数据(docID)是有顺序的,默认是写入顺序,在大部分情况下,当检索数据时,都需要遍历倒排索引里的所有docID,然后对当前document的数据做解析。
当我们希望对检索的数据按照某个字段做排序,且仅仅取结果集的top n时,还是需要遍历倒排索引里的所有数据。因为每个document中的字段是无序的,只有遍历了所有的document时才知道哪些是top n. 这样就存在很大的性能问题,毕竟当倒排索引的数据量很大时,遍历处理过程需要耗费很长的时间,比如:'获取北京市地区订单金额最大的10笔订单',就要遍历北京市的所有订单。Index Sorting就是提高性能的方式。
IndexSorting,就是对索引里的数据做排序,不仅仅是倒排索引,Segment里的所有数据都是,包括正向索引,docValues,倒排索引等等。使这些数据结构里的数据不再按照原来的写入顺序排序,而是按照指定的Field,ASC/DESC形式来排序,这样当我们检索时排序方式契合IndexSorting的形式,且不统计命中总数,不计算最大评分,仅仅取top n的数据时,就能触发Early Termination 机制,不再需要遍历所有的document,仅仅按照顺序处理,当符合要求的数据达到n时,直接结束。
IndexSorting是一种预排序
与查询时的Sort不同,IndexSorting是一种预排序,即数据预先按照某种方式进行排序,它是Index的一个设置,不可更改。大家知道,Elasticsearch的底层是Lucene,Lucene中是以Segment为单位进行查询的,这里说的IndexSorting对数据进行预排序也是在每个Segment内有序的。
一个Segment中的每个文档,都会被分配一个docID,docID从0开始,顺序分配。在没有IndexSorting时,docID是按照文档写入的顺序进行分配的,在设置了IndexSorting之后,docID的顺序就与IndexSorting的顺序一致。
举个例子来说,假如文档中有一列为Timestamp,我们在IndexSorting中设置按照Timestamp逆序排序,那么在一个Segment内,docID越小,对应的文档的Timestamp越大,即按照Timestamp从大到小的顺序分配docID。
IndexSorting使用方式
IndexSorting需要在创建索引时在Mappings和Settings里指定,具体使用方式如下:
单Field排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
多Field排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
当通过配置 index.sort.field
,index.sort.order
两个选项后,Elasticsearch在Refresh时,会对当前内存新写入的数据根据这两个配置项作重新排序
,然后生成Segment。这几个Field构成的排序机制就类似于Mysql的聚集索引
,且可以是复合聚集索引
。当搜索的数据是按照主键索引排序
,且不是全表查询
,不统计总数
时,就能发挥主键索引的所用,能极大的提高检索效率。
总结
Elasticsearch Index Sorting 是通过调整Segment里的数据顺序来契合检索时的顺序
,以达到在检索时能够按照Sort里的顺序来对document做处理
,当取到足量的满足条件的数据时 Early Terminate
,忽略后续所有的document,当指定Field值的倒排索引的数据量很大时,能够极大的提升检索时的效率。