我的日常

登录/注册
您现在的位置:论坛 资料库 开源社区 > Solr如何使用游标进行深度分页查询
总共48087条微博

动态微博

查看: 2176|回复: 1

Solr如何使用游标进行深度分页查询

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2016-08-23 14:22:04 |只看该作者 |倒序浏览
    通常,我们的应用系统,如果要做一次全量数据的读取,大多数时候,采用的方式会是使用分页读取的方式,然而
    分页读取的方式,在大数据量的情况下,在solr里面表现并不是特别好,因为它随时可能会发生OOM的异常,在solr里面
    通过rows和start参数,非常方便分页读取,但是如果你的start=1000000 rows=10,那么solr里面会将前面100万元数据的索引信息读取在内存里面,这样以来,非常耗内存,所以在solr里面,分页并不适合深度分页。


    深度分页在solr里面,更推荐使用游标的方式,游标是无状态的,不会维护索引数据在内存里面,仅仅记录最后一个doc的计算值类似md5,然后每一次读取,都会如此记录最后一个值的mark,下一次通过这个mark便能快速的定位到第二页上,如此往复,便能完成整个数据的读取。而且耗费内存非常少。

    假如现在有排好队的10个人等待买饭,而一个房间里面最多一次只能进2个人,那么我们就可以将这个2个人,编号顺序,1和2,他们打完饭后,让2号的人通知,下一组2个人,进来打饭,如此往复
    所有人都能吃到饭,这就类似solr中游标的使用。


    使用游标的方式读取数据,也有一些约束或者缺点:

    (1)查询条件里面必须有cursorMark参数,而且必须不能有start参数
    (2)查询的条件里必须按照主键排序(升序或降序),如果没有这个条件,主键重复,那么会造成多个游标的mark值,这样以来下一次请求就不知道如何定位了,而且有可能出现重复读数据的情况
    (3)如果一个分页的系统,按照指定页码跳转的功能,这样实现的功能是实现不了的,因为游标一旦读取了,就不能再返回上一次的位置了,这种业务最好使用start+rows搞定。


    solrj实现代码例子:
    1. //游标查询
    2.     public static void cursorQuery()throws Exception{
    3.             //http solr服务
    4.             HttpSolrClient sc=new HttpSolrClient("http://localhost:8983/solr/one");
    5.             //solr查询封装
    6.             SolrQuery sq =new SolrQuery();
    7.                 sq.setRows(2);//设置游标一次读的数量
    8.                 sq.set("q", "*:*");//按条件检索
    9.                 sq.setSort("id", ORDER.asc);//根据主键排序
    10.                 String cursorMark = CursorMarkParams.CURSOR_MARK_START;//游标初始化
    11.                 boolean done = false;
    12.                 while (!done) {
    13.                     sq.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);//变化游标条件
    14.                     QueryResponse rsp = sc.query(sq);//执行多次查询读取
    15.                     String nextCursorMark = rsp.getNextCursorMark();//获取下次游标
    16.                     //做一些操作数据的事   
    17.                     for(SolrDocument sd:rsp.getResults()){
    18.                         System.out.println(sd.get("id"));
    19.                     }
    20.                     //如果两次游标一样,说明数据拉取完毕,可以结束循环了
    21.                     if (cursorMark.equals(nextCursorMark)) {
    22.                         done = true;
    23.                     }
    24.                     cursorMark = nextCursorMark;
    25.                 }
    26.                 //关闭连接
    27.                 sc.close();
    28.     }
    复制代码





    科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    4

    主题

    0

    听众

    302

    金钱

    四袋长老

    该用户从未签到

    沙发
    发表于 2016-09-27 14:11:52 |只看该作者
    涨姿势了                                   
    回复

    使用道具 举报

    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表