千家信息网

elasticsearch的ScanScroll如何使用

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这篇文章主要讲解了"elasticsearch的ScanScroll如何使用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"elasticsearch的
千家信息网最后更新 2024年09月22日elasticsearch的ScanScroll如何使用

这篇文章主要讲解了"elasticsearch的ScanScroll如何使用",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"elasticsearch的ScanScroll如何使用"吧!

ScanScroll 的特点

  1. 优点

    1. 速度快

    2. 大数据量

  2. 缺点

    1. 不支持排序

    2. 不支持分页

    3. 不支持评分

    4. 不支持续查


使用场景

看起来,缺点要比优点多很多,不过它很有用。如果说BULK是为了快速入库存在的,那SCAN就是为了快速出库而诞生的。ES的查询性能优越,但是分析能力弱。所以会有,比如把ES的数据拉到Hadoop集群去分析计算的需求,当然这个已经有现成的插件了,不出所料也是用的SCAN。如果SCAN遭遇BULK, 也就是ES到ES的话,它有另一个更熟悉的名字叫 复制表。

使用方法

def scanTest():    searchRes = es.search(index="users",size=10,body={"query": {"match_all": {}}},search_type="scan",scroll="10s")    while True:        scrollRes=es.scroll(scroll_id=searchRes["_scroll_id"],scroll="10s",ignore=[400, 404])        res_list = scrollRes["hits"]["hits"]        if not len(res_list):            break;        for res in res_list:            print res["_source"]["userName"]

原理流程

整个流程比较清晰,先count一个总数,下面每次scroll,返回size*分片数的数据,直到遍历全部。SCAN是支持查询偏好preference的,可以指定分片,所以有人说的size*主分片数,是不准确的,这个很容易验证。

  • 第一阶段:Search

    • 用TotalHitCountCollector统计下总数,并且确定(节点,查询上下文ID),Base64编码成ScrollId返回

  • 第二阶段:SearchScroll

    • 根据ScrollId去每个节点,找到查询上下文ID执行XFilteredQuery,收集结果,合并返回


第一阶段除了返回总数,还有一个很神秘的ScrollId,这个ScrollId长成这样,很像Base64编码过的。一定不是ID那么简单,了解一番,果不其然 ,主要有3个部分组成type,context,attributes

  1. type 分别是queryThenFetch,queryAndFetch,scan,我们这里讲的是scan

  2. attributes 只有一个元素,total_hits

  3. context 是个分片的元组,有2个元素,分片 = [节点ID,查询上下文ID]

ScrollId 是个很容易会暴露秘密的东西,我们会发现ScrollId 依赖的节点ID和查询上下文ID都是变量,查询上下文ID,每次请求都要递增的。所以每次请求的ScrollId 都不一样,导致了如果在我们的SCAN过程意外终止,我们可能需要重新来过。

每次SCAN,处理Scroll跳到下一页去,我们自己指定form是无效的。

//SearchServiceprivate void processScroll(InternalScrollSearchRequest request, SearchContext context) {        // process scroll        context.from(context.from() + context.size());        context.scroll(request.scroll());        // ... }
//ScanContextpublic TopDocs execute(SearchContext context) throws IOException {        ScanCollector collector = new ScanCollector(readerStates, context.from(), context.size(), context.trackScores());        Query query = new XFilteredQuery(context.query(), new ScanFilter(readerStates, collector));        try {            context.searcher().search(query, collector);        } catch (ScanCollector.StopCollectingException e) {            // all is well        }        return collector.topDocs();}

自定义的Filter,Collector,执行搜索,收集那一页的结果集

 //ScanContext public void collect(int doc) throws IOException {            if (counter >= from) {                docs.add(new ScoreDoc(docBase + doc, trackScores ? scorer.score() : 0f));            }            readerState.count++;            counter++;            if (counter >= to) {                throw StopCollectingException;            }}

根据以往数据库的认识,count操作总是很慢的,这让我很担心会延长整个查询的时间,后来我发现这种担心是多余的,对于全文检索count操作是很快速的。根据测试,17亿数据24个分片,平均每个分片的count时间在200ms到700ms之间,最糟糕的情况下总数也能在1秒内返回,这对于整个查询时间而言是可以接受的。

感谢各位的阅读,以上就是"elasticsearch的ScanScroll如何使用"的内容了,经过本文的学习后,相信大家对elasticsearch的ScanScroll如何使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0