elasticsearch-php使用scroll深度分页处理数据(附代码)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LJFPHP/article/details/90052630

一、前言

      在刚开始学习ES的时候,觉得自带的from+size就足够使用了,但是在后续的学习中,不断看到一种说法,就是from+size,在要获取10000+10的时候就很影响性能。既然我们使用elasticsearch来处理大数据,那取10000条数据简直不要太随便,况且size默认不能超过10000,超过的话还要设置index.max_result_window参数,实在麻烦。所以博主这里使用scroll来实现数据的遍历查询。

相关链接:
Elasticsearch:from&size返回值最大记录的修改设置
Elasticsearch——分页查询From&Size VS scroll

相关概念请看上面两篇博文,咱们这里不一一赘述了,直接开始php操作

二、操作实例

1、在es-php使用scroll的文档

官方scroll文档:https://www.elastic.co/guide/cn/elasticsearch/php/current/search_operations.html#scrolling%E6%B8%B8%E6%A0%87%E6%9F%A5%E8%AF%A2

2、代码

 public function getIndexByTime($start,$end)
    {
        $start = strtotime($start) + 600;  // 冗余10分钟的数据
        $end =  strtotime($end);
        //组装搜索的索引
        $params = [
            'index' => $date_arr['index'], //多索引一起用,逗号隔开以数组的形式传过去,实测可以
            'type' => '_doc',  // type必须保持一致,且索引建立之后,无法更改索引
            "scroll" => "30s",   //这个代表每次翻页的时间间隔
            "size" => 1000,  //代表每次分页查询的条数
            'body' => [
                "_source" => [
                    "includes" => ["pixel.is50mClient","pixel.newbie", "pixel.channel", "pixel.os", "pixel.type", "pixel.user_id", "pixel.uuid", "*country_code2","clientip", "timestamp","@timestamp"],   //查询的字段,最好是把自己需要的字段都列出来,不要查太多冗余字段
                ],
                'query' => [
                    "bool" => [
                        "filter" => [
                            "range" => [
                                "@timestamp" => [
                                    "gt" => $start_range,
                                    "lt" => $end_range,
                                ]
                            ],
                        ],
                    ]
                ]
            ]
        ];
        $repos =  $this->client->search($params);
        while (isset($repos['hits']['hits']) && count($repos['hits']['hits']) > 0) {
            foreach($repos['hits']['hits'] as $key=>$v)
            {
             // 这里写上你的逻辑
            $scroll_id = $repos['_scroll_id'];
            $repos = $this->client->scroll([    //这里通过while循环,取得上次的scroll_id,继续查询,直到查不出来数据位置
                    "scroll_id" => $scroll_id,
                    "scroll" => "30s"
                ]
            );
        }
    }

大概的代码如上,可以参照注释部分理解。

三、需要注意的地方

1、出现内存不够的情况,报错

Out of memory (allocated 364904448) (tried to allocate 262144 bytes)

      这个报错是php的报错,也就是查出的内存超过了php设置的内存。一般我们本地的内存设置成128M是够用的。所以出现这个情况优先考虑自己是不是操作查出的数组太频繁,foreach数组占用大量内存等。

2、搜索字段少一些

博主在出现内存告急之后试了下:

当搜索字段是全字段的时候,size超过200条就出现内存不足的情况
当搜索字段只列出需要的部分,size设置400条就出现内存不足的情况
当搜索字段只有一个的时候,size部分设置1000都可以

      综上所述,我们可以知道,在查询的时候,查出的字段要尽量的少,其次是size设置成合适的大小。(这部分只是举个例子,内存告急是代码部分的问题,修改之后就好了。)
优化数组内存部分:https://blog.csdn.net/LJFPHP/article/details/90053455

3、不够灵活

      当结果足够大的时候, scroll 性能更佳。但是不灵活和 scroll_id 难管理问题存在。使用 scroll 必须是按照顺序一页一页进行翻阅,如果是无规则的翻页,它的性能消耗也是极大的。这部分我们可以理解为类似于抖音视频的那种样子,我们看的时候只能往下拉而不能直接选择跳到多少页。因为跳页操作对于大数据来说是非常耗费性能的,对scroll来说也一样。所以大家要根据自己的实际需求去选择分页的方式。

      博主这里的数据对实时性要求不是很高,也不需要进行跳页操作,所以选用了scroll的方式,大家仁者见仁智者见智吧。加油!

end

猜你喜欢

转载自blog.csdn.net/LJFPHP/article/details/90052630