之前一直使用from size进行分页查询(深度分页),当数据量大的时候,对全部数据进行遍历,使用from size性能会很差,然后了解了下scroll方法,简单讲解一下scroll方法的使用。

从网上了解到,scroll类似于数据库中的游标,不考虑排序的时候,可以结合SearchType.SCAN使用。


1.首先,创建一个school索引,分片数量为5

es scoller翻页优化 es scroll 分页_System

2.使用以下方法,来创造一些简单的假数据

/**
     * 创造假数据
     * @param count 数据量
     */
    public static void insertData(int count) {
        System.out.println("-----------begin------------");
        Student student=new Student();
        for (int i=1;i<=count;i++){
            student.setName("name"+i);
            student.setId(i);
            String id="id_"+i;//设置存入ES中的ID
            //插入数据(数据量大时,最好使用批量插入,此处为单条插入)
            esUtils.insert("school","student",id,new Gson().toJson(student));
        }
        System.out.println("-----------end------------");
    }

Sudent类

package com.es.scroll.bean;


public class Student {
    private String name;
    private int id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

ElasticsearchUtils

package com.es.scroll.esutil;

import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;


public class ElasticsearchUtils {

    private Client client;

    public ElasticsearchUtils(String clusterName, String ipAddress,int port) {
        Settings settings = ImmutableSettings
                .settingsBuilder()
                //设置集群名称 
                .put("cluster.name", clusterName)
                .put("client.transport.ignore_cluster_name", false)
                .put("node.client", true).put("client.transport.sniff", true)
                .build();
        client = new TransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(ipAddress,
                        port));
    }

    public Client getClient(){
        return this.client;
    }


    /**
     * 创建索引
     * @param indexName 索引名称,相当于数据库名称
     * @param typeName 索引类型,相当于数据库中的表名
     * @param id id名称,相当于每个表中某一行记录的标识
     * @param jsonData json数据
     */
    public void insert(String indexName, String typeName, String id,
                            String jsonData) {
        IndexRequestBuilder requestBuilder = client.prepareIndex(indexName,
                typeName, id).setRefresh(true);//设置索引名称,索引类型,id
        requestBuilder.setSource(jsonData).execute().actionGet();//创建索引
    }
}

数据如下:




es scoller翻页优化 es scroll 分页_elasticsearch_02


3.使用scroll结合scan遍历所有数据

package com.es.scroll;

import com.es.scroll.bean.Student;
import com.es.scroll.esutil.ElasticsearchUtils;
import com.google.gson.Gson;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;




public class MainApplication {
    private static int i=0;
    private static ElasticsearchUtils esUtils;

    public static void main(String[] args) {

        //创建ElasticsearchUtils对象,设置集群名称,IP地址,端口号
         esUtils = new ElasticsearchUtils("im_shanmenglu", "localhost", 9300);
        //        insertData(10000);
        //获取Client对象,设置索引名称,搜索类型(SearchType.SCAN),搜索数量,发送请求
        SearchResponse searchResponse = esUtils.getClient()
                .prepareSearch("school").setSearchType(SearchType.SCAN)
                .setSize(10).setScroll(new TimeValue(20000)).execute()
                .actionGet();//注意:首次搜索并不包含数据
        //获取总数量
        long totalCount = searchResponse.getHits().getTotalHits();
        int page=(int)totalCount/(5*10);//计算总页数,每次搜索数量为分片数*设置的size大小
        System.out.println(totalCount);
        for (int i = 0; i <= page; i++) {
            //再次发送请求,并使用上次搜索结果的ScrollId
            searchResponse = esUtils.getClient()
                    .prepareSearchScroll(searchResponse.getScrollId())
                    .setScroll(new TimeValue(20000)).execute()
                    .actionGet();
            parseSearchResponse(searchResponse);
        }

    }

    public static void parseSearchResponse(SearchResponse searchResponse) {
        SearchHits hits = searchResponse.getHits();
        System.out.println("-----------begin------------");
        for (SearchHit searchHit : hits.getHits()) {
            try {
                i++;
                String id = searchHit.getId();
                System.out.println("第" + i + "条数据:" + id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("-----------end------------");
    }

    /**
     * 创造假数据
     * @param count 数据量
     */
    public static void insertData(int count) {
        System.out.println("-----------begin------------");
        Student student=new Student();
        for (int i=1;i<=count;i++){
            student.setName("name"+i);
            student.setId(i);
            String id="id_"+i;//设置存入ES中的ID
            //插入数据(数据量大时,最好使用批量插入,此处为单条插入)
            esUtils.insert("school","student",id,new Gson().toJson(student));
        }
        System.out.println("-----------end------------");
    }


}

/**部分数据
 * 10000
 -----------begin------------
 第1条数据:id_11
 第2条数据:id_16
 第3条数据:id_23
 第4条数据:id_28
 第5条数据:id_30
 第6条数据:id_35
 第7条数据:id_42
 第8条数据:id_47
 第9条数据:id_2
 第10条数据:id_7
 第11条数据:id_12
 第12条数据:id_17
 第13条数据:id_24
 第14条数据:id_29
 第15条数据:id_31
 第16条数据:id_36
 第17条数据:id_43
 第18条数据:id_48
 第19条数据:id_3
 第20条数据:id_8
 第21条数据:id_13
 第22条数据:id_18
 第23条数据:id_20
 第24条数据:id_25
 第25条数据:id_32
 第26条数据:id_37
 第27条数据:id_44
 第28条数据:id_49
 第29条数据:id_4
 第30条数据:id_9
 第31条数据:id_14
 第32条数据:id_19
 第33条数据:id_21
 第34条数据:id_26
 第35条数据:id_33
 第36条数据:id_38
 第37条数据:id_40
 第38条数据:id_45
 第39条数据:id_52
 第40条数据:id_5
 第41条数据:id_10
 第42条数据:id_15
 第43条数据:id_22
 第44条数据:id_27
 第45条数据:id_34
 第46条数据:id_39
 第47条数据:id_41
 第48条数据:id_46
 第49条数据:id_1
 第50条数据:id_6
 -----------end------------
 -----------begin------------
 第51条数据:id_54
 第52条数据:id_59
 第53条数据:id_61
 第54条数据:id_66
 第55条数据:id_73
 第56条数据:id_78
 第57条数据:id_80
 第58条数据:id_85
 第59条数据:id_92
 第60条数据:id_102
 第61条数据:id_50
 第62条数据:id_55
 第63条数据:id_62
 第64条数据:id_67
 第65条数据:id_74
 第66条数据:id_79
 第67条数据:id_81
 第68条数据:id_86
 第69条数据:id_93
 第70条数据:id_103
 第71条数据:id_51
 第72条数据:id_56
 第73条数据:id_63
 第74条数据:id_68
 第75条数据:id_70
 第76条数据:id_75
 第77条数据:id_82
 第78条数据:id_87
 第79条数据:id_94
 第80条数据:id_104
 第81条数据:id_57
 第82条数据:id_64
 第83条数据:id_69
 第84条数据:id_71
 第85条数据:id_76
 第86条数据:id_83
 第87条数据:id_88
 第88条数据:id_90
 第89条数据:id_95
 第90条数据:id_100
 第91条数据:id_53
 第92条数据:id_58
 第93条数据:id_60
 第94条数据:id_65
 第95条数据:id_72
 第96条数据:id_77
 第97条数据:id_84
 第98条数据:id_89
 第99条数据:id_91
 第100条数据:id_101
 -----------end------------
 -----------begin------------
 第101条数据:id_107
 第102条数据:id_114
 第103条数据:id_119
 第104条数据:id_121
 第105条数据:id_126
 第106条数据:id_133
 第107条数据:id_138
 第108条数据:id_97
 第109条数据:id_171
 第110条数据:id_176
 第111条数据:id_108
 第112条数据:id_110
 第113条数据:id_115
 第114条数据:id_122
 第115条数据:id_127
 第116条数据:id_134
 第117条数据:id_139
 第118条数据:id_98
 第119条数据:id_172
 第120条数据:id_177
 第121条数据:id_109
 第122条数据:id_111
 第123条数据:id_116
 第124条数据:id_123
 第125条数据:id_128
 第126条数据:id_130
 第127条数据:id_135
 第128条数据:id_99
 第129条数据:id_166
 第130条数据:id_173
 第131条数据:id_105
 第132条数据:id_112
 第133条数据:id_117
 第134条数据:id_124
 第135条数据:id_129
 第136条数据:id_131
 第137条数据:id_136
 第138条数据:id_143
 第139条数据:id_179
 第140条数据:id_181
 第141条数据:id_106
 第142条数据:id_113
 第143条数据:id_118
 第144条数据:id_120
 第145条数据:id_125
 第146条数据:id_132
 第147条数据:id_137
 第148条数据:id_96
 第149条数据:id_168
 第150条数据:id_170
 -----------end------------
 -----------begin------------
 第151条数据:id_183
 第152条数据:id_140
 第153条数据:id_145
 第154条数据:id_152
 第155条数据:id_157
 第156条数据:id_164
 第157条数据:id_169
 第158条数据:id_188
 第159条数据:id_190
 第160条数据:id_195
 第161条数据:id_184
 第162条数据:id_141
 第163条数据:id_146
 第164条数据:id_153
 第165条数据:id_158
 第166条数据:id_160
 第167条数据:id_165
 第168条数据:id_189
 第169条数据:id_191
 第170条数据:id_196
 第171条数据:id_178
 第172条数据:id_180
 第173条数据:id_142
 第174条数据:id_147
 第175条数据:id_154
 第176条数据:id_159
 第177条数据:id_161
 第178条数据:id_185
 第179条数据:id_192
 第180条数据:id_197
 第181条数据:id_186
 第182条数据:id_148
 第183条数据:id_150
 第184条数据:id_155
 第185条数据:id_162
 第186条数据:id_167
 第187条数据:id_174
 第188条数据:id_193
 第189条数据:id_198
 第190条数据:id_201
 第191条数据:id_175
 第192条数据:id_182
 第193条数据:id_144
 第194条数据:id_149
 第195条数据:id_151
 第196条数据:id_156
 第197条数据:id_163
 第198条数据:id_187
 第199条数据:id_194
 第200条数据:id_199
 -----------end------------
 */



此处截取了部分输出数据,可以看出使用scroll进行分页查询,每次查询的数据量为分片的数量*首次查询设置的size大小,TimeValue表示需要保持搜索的上下文时间。