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

通常,我们的应用系统,如果要做一次全量数据的读取,大多数时候,采用的方式会是使用分页读取的方式,然而 分页读取的方式,在大数据量的情况下,在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实现代码例子:

Java代码

  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. }

参考文档: https://cwiki.apache.org/confluence/display/solr/Pagination+of+Results

原文发布于微信公众号 - 我是攻城师(woshigcs)

原文发表时间:2016-03-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DOTNET

Entity Framework——建模建库

1数据库初始化策略选择 三种初始化策略: 1)CreateDatabaseIfNotExists:默认的策略。如果数据库不存在,那么就创建数据库。但是如果数据库...

32470
来自专栏维C果糖

史上最简单的 MySQL 教程(四)「SQL 基本操作 之 库操作」

根据操作对象的不同,咱们可以将 SQL 的基本操作分为三类,分别为:库操作、表(字段)操作和数据操作。

454130
来自专栏java学习

Hibernate学习笔记2

定义hbm.xml映射文件和pojo类时都需要定义主键,Hibernate中定义的主键类型包括:自然主键和代理主键:

11540
来自专栏GreenLeaves

oracle 表空间tablespace

一、Oracle 表空间的组成 Everoone knows Oracle数据库真正存放数据的是数据文件,Oracle表空间是逻辑上的概念,他在物理上是并不存在...

36780
来自专栏开发与安全

从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象

一、用模板实现单例模式 在前面的文章中,用过多种方法实现单例模式,现在用模板方式来实现: 为了实现线程安全,需要在linux 下使用pthread_mutex_...

34100
来自专栏咸鱼不闲

solr中使用IKAnalyzer配置同义词,停止词,扩展词

第一步 将IKAnalyzer2012FF_u1放到solr-4.7.2/example/solr-webapp/webapp/WEB-INF/lib 目录下 ...

17640
来自专栏祝威廉

ElasticSearch QueryCache漫谈

这些天在做ES调优,因为之前更多的是考虑ES的架构和可运维性,并没有过多关注query调优这块。今天一查Query Cache相关的内容,发现是少之又少。于是自...

19820
来自专栏性能与架构

分库后如何处理分页?

在数据量过大以后,通常都会进行分库操作,把一张表拆分到不同数据库中 例如 tb1 表被拆分到3个库中,分库1、分库2、分库3 现在想执行分页操作 SELECT ...

34180
来自专栏刺客博客

PHP利用phpexcel导入Excel表到Mysql数据库

1.5K30
来自专栏魏琼东

一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-演示ORM的批量删除与更新

系列回顾           前面的文章一步一步教你使用AgileEAS.NET基础类库进行应用开发-基础篇-演示ORM的基本操作和一步一步教你使用AgileE...

22580

扫码关注云+社区

领取腾讯云代金券