表格存储新手指南:如何实现分页查询

本篇文章会介绍如何在表格存储上实现分页查询。

有别于传统关系型数据库支持的翻页查询,在NoSQL的数据模型和API上,实现分页功能会有以下的限制,需要特别注意:

  1. 不支持获取整个范围的行数,即无法计算总的页数。
  2. 不建议使用设置offset来跳页,因为offset的过滤是在客户端做,服务端不管如何,都会扫描读出那么多的数据。若offset设定过大,则可能导致本次查询时间过长。
  3. 最佳实践是只提供顺序翻页的功能,一页一页顺序往下翻。

下面是一个实现分页读接口的示例代码,提供offset过滤以及读取指定页数的数据:

    /**
     * 范围查询指定范围内的数据,返回指定页数大小的数据,并能根据offset跳过部分行。
     */
    private static Pair<List<Row>, RowPrimaryKey> readByPage(OTSClient client, String tableName,
            RowPrimaryKey startKey, RowPrimaryKey endKey, int offset, int pageSize) {
        Preconditions.checkArgument(offset >= 0, "Offset should not be negative.");
        Preconditions.checkArgument(pageSize > 0, "Page size should be greater than 0.");

        List<Row> rows = new ArrayList<Row>(pageSize);
        int limit = pageSize;
        int skip = offset;

        RowPrimaryKey nextStart = startKey;

        // 若查询的数据量很大,则一次请求有可能不会返回所有的数据,我们需要流式的将所需要的数据全部查出来。
        while (limit > 0 && nextStart != null) {
            // 构造GetRange的查询参数。
            // 注意:startPrimaryKey需要设置为上一次读到的位点,从上一次未读完的地方继续往下读,实现流式的范围查询。
            RangeRowQueryCriteria criteria = new RangeRowQueryCriteria(tableName);
            criteria.setInclusiveStartPrimaryKey(nextStart);
            criteria.setExclusiveEndPrimaryKey(endKey);

            // 需要设置正确的limit,这里期望读出的数据行数最多就是完整的一页数据以及需要过滤(offset)的数据
            criteria.setLimit(skip + limit);

            GetRangeRequest request = new GetRangeRequest();
            request.setRangeRowQueryCriteria(criteria);
            GetRangeResult response = client.getRange(request);
            for (Row row : response.getRows()) {
                if (skip > 0) {
                    skip--; // 对于offset之前的数据,我们需要过滤掉,采用的策略是读出来后在客户端进行过滤。
                } else {
                    rows.add(row);
                    limit--;
                }
            }

            // 设置下一次查询的起始位点
            nextStart = response.getNextStartPrimaryKey();
        }

        return new Pair<List<Row>, RowPrimaryKey>(rows, nextStart);
    }


下面是使用以上接口,顺序的一页一页读取某个指定范围内的所有数据的例子:

    private static void readByPage(OTSClient client, String tableName) {
        int pageSize = 8;
        int offset = 33;

        RowPrimaryKey startKey = new RowPrimaryKey();
        startKey.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.INF_MIN);
        startKey.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MIN);

        RowPrimaryKey endKey = new RowPrimaryKey();
        endKey.addPrimaryKeyColumn(COLUMN_GID_NAME, PrimaryKeyValue.INF_MAX);
        endKey.addPrimaryKeyColumn(COLUMN_UID_NAME, PrimaryKeyValue.INF_MAX);
        // 读第一页,从范围的offset=33的行开始读起
        Pair<List<Row>, RowPrimaryKey> result = readByPage(client, tableName, startKey, endKey, offset, pageSize);
        for (Row row : result.getKey()) {
            System.out.println(row.getColumns());
        }
        System.out.println("Total rows count: " + result.getKey().size());

        // 顺序翻页,读完范围内的所有数据
        startKey = result.getValue();
        while (startKey != null) {
            System.out.println("============= start read next page ==============");
            result = readByPage(client, tableName, startKey, endKey, 0, pageSize);
            for (Row row : result.getKey()) {
                System.out.println(row.getColumns());
            }
            startKey = result.getValue();
            System.out.println("Total rows count: " + result.getKey().size());
        }
    }

完整的例子可以从这里下载。

时间: 2024-08-31 02:28:43

表格存储新手指南:如何实现分页查询的相关文章

表格存储新手指南:Java SDK异步接口的使用

本篇文章主要会介绍下表格存储的Java SDK提供的异步接口,如何使用以及应用场景. 为什么需要异步? 异步提供了一个non-blocking, event-driven的编程模型,能够将系统不同层级的模块进行层次化的解耦,能够利用多核并行执行任务,提高性能. 现如今,一个大型的系统,系统级调优的最关键一步,就是异步化.异步化最常改造的是远程RPC或者数据库访问部分,表格存储作为一个底层数据库产品,需要提供异步接口来适应这个潮流. 在表格存储内部,我们也有一些使用异步来优化系统的例子,就拿Jav

表格存储数据模型和查询操作

摘要        本篇文章主要会详细聊一下表格存储的查询操作,以及如何根据业务的需求来设计表结构以支持特定条件的查询.        在理解查询操作之前,会简单描述一下表格存储的数据模型,以加深对查询操作的理解. 数据模型 表格存储(TableStore)的数据模型可以简化为使用下面这个数据结构来表示: 表格存储数据模型: SortedMap<PrimaryKey, List<Column>>        逻辑上理解表格存储的数据模型,就是一个SortedMap,只不过这是一个

ligerui-LigerUI 表格分页查询显示页数不对,源码bug 如何修改

问题描述 LigerUI 表格分页查询显示页数不对,源码bug 如何修改 将usePager置为true,增加查询功能,点击最后一页的箭头按钮,然后再点击查询,在页码栏会显示错误求大牛帮忙解决.此部分是在源码中的 解决方案 http://my.oschina.net/lishixi/blog/87091

ssh框架jsp分页查询中如何对迭代器生成的表格中的一行记录进行删除修改操作?

问题描述 ssh框架jsp分页查询中如何对迭代器生成的表格中的一行记录进行删除修改操作? 求此处的链接操作delete及modify的实现代码,求大神帮忙,万分感谢! 解决方案 JSP: //单个删除 function ch(id){ if(confirm("确定要删除吗?")){ window.location.href="user_del.action?delid="+id; } } Action中: private Integer delid; //从页面中获

表格存储的宽行流式读功能

本篇文章介绍表格存储中的宽行流式读功能,简单说就是介绍如何读取一个列很多数据量很大的行,当一次读取不出整行时如何分多次读取,当只需要读取宽行的一部分时如何读取可以性能更好. 宽行与宽行流式读 表格存储的表结构设计中,每行由主键列和属性列构成,主键列按照顺序构成一个主键,唯一的确定一行.读写某一行时,我们必须指定这一行的主键,然后写入或者读取其中的某些属性列. 主键列的名称和类型是在建表时确定好的,作为TableMeta的一部分.但是属性列的列名和数量却是不需要指定的,在实际写入某一行时可以任意设

表格存储技术方案实践及客户案例分享

表格存储是一款2014年10月份正式商业化的NoSQL数据存储服务,在商业化之前,早在2010年就在阿里云内部开始使用,云邮箱和云OS都是表格存储最早的一批用户.到目前,无论是在阿里集团内部还是在公共云环境上,在移动社交.金融风控.电商物流.存储备份.物联网IoT.日志监控.大数据分析报表等领域都有着广泛的用户基础与成熟的实践方案. 为了方便更多的用户了解和使用表格存储,该帖子会将最近非常有参考意义的方案设计.技术实践及相关客户分享的博客文章汇总到这里,大家可以在这里快速查找到和自己业务场景相近

ExtJs 备忘录(6)—— GirdPanl表格(二) [ 搜索分页 ]

前言 近些天对于厚积薄发有深刻的理解,尤其是月末那两天,很想再写两篇文章,保持每周一篇--每月至少四篇以上的文章.写文章分两种情况:一种情况是已经积累了许多经验,写起来轻松且得心应手,内容和系列文章容易把握,最典型的就是视频监控的那系列文章,得以写完是因为已经从事近半年相关的开发工作;另一种情况则是有方向但积累不足甚至无积累,边学边实践,然后进行归类和总结成系列,比如视频监控第二个系列和本系列都属于这种情况,如果时间稍微充足且过程较为顺利,尚可勉强完成,反之则遥遥无期.由此感悟,下次写系列文章还

表格存储如何实现高可靠和高可用

系列文章 表格存储如何实现高可靠和高可用表格存储如何实现跨区域的容灾 前言 本文会介绍一款分布式NoSQL如何实现数据高可靠和服务高可用,这是一款云上的NoSQL服务,叫做表格存储.对于分布式NoSQL,大家可能会想到很多名字,比如HBase.Cassandra,AWS的DynamoDB等,这类NoSQL在设计之初就作为一个分布式系统支持超大规模的数据量与并发.此外大家可能还会想到MongoDB和Redis,这两个也提供集群功能,但是一般需要人为的配置sharding和复制集/主从等. 表格存储

表格存储结合Elasticsearch进行搜索的场景分析和实践

表格存储结合Elasticsearch进行搜索的场景分析和实践 表格存储(TableStore)是什么 TableStore是一个构建在阿里云飞天分布式系统上的Nosql数据库服务,熟悉阿里云的同学肯定听说过飞天5K,飞天是一个可以管理5000台机器的分布式系统,TableStore作为构建在其上的一个Nosql数据库,可以承载海量(单表几百TB)的数据存储,同时数据有三份拷贝,数据安全性有极高的保证. TableStore的数据是以行进行组织的,每行包含多个主键列和多个属性列,主键列的列名和类