Skip to content

查询接口

Shen Yunlong edited this page Aug 8, 2023 · 8 revisions

查询接口支持根据主键或者主键的范围进行扫描,也可以不指定主键,根据索引或者索引前缀范围进行扫描查询,同时可以对非主键列指定过滤条件,只有满足条件的行才会返回。

1. 示例

下面是两个查询的例子:

  1. 查询 test_table表 c2, c3 列,主键范围为 1000 <= c1 <= 2000,并且c2 == 0,c3 > 100 的数据行
// create table test_table(c1 int, c2 int, c3 int, primary key(c1)) partition by key(a) partitions 16;
int rowkeyStart = 1000L;
int rowkeyEnd = 2000L;
QueryResultSet resultSet  = obTableClient.query("test_table")
                                         .select("c2","c3")
                                         .setScanRangeColumn("c1")
                                         .addScanRange(rowkeyStart, rowkeyEnd)
                                         .setFilter(andList(compareVal(ObCompareOp.EQ, "c2", 0),
                                                            compareVal(ObCompareOp.GT, "c3", 100)))
                                         .execute();

for (int i = 0; i < resultSet.cacheSize(); i++) {
    resultSet.next();
    Map<String, Object> row = resultSet.getRow();
    for (Map.Entry<String, Object> entry : row.entrySet()) {
        System.out.println(entry.getKey() + "," + entry.getValue());
    }
}  
  1. 查询 test_index表 c1, c2 列,索引范围为 c1 == 0, 2 <= c3 <=40,并且c4 > 100 的数据行
// create table test_index(c1 int, c2 int, c3 int, c4 int, primary key(c1, c2), index idx1(c1, c3)) local) partition by key(c1) partitions 16;
QueryResultSet resultSet  = obTableClient.query("test_index")
                                         .select("c1","c2")
                                         .setScanRangeColumn('c1', "c3")
                                         .indexName("c1_c3_idx")
                                         .addScanRange(new Object[]{0, 2}, new Object[]{0, 40})
                                         .setFilter(compareVal(ObCompareOp.GT, "c4", 100))
                                         .execute();

for (int i = 0; i < resultSet.cacheSize(); i++) {
    resultSet.next();
    Map<String, Object> row = resultSet.getRow();
    for (Map.Entry<String, Object> entry : row.entrySet()) {
        System.out.println(entry.getKey() + "," + entry.getValue());
    }
} 

2. 设置投影列

每次查询需要指定返回结果的列(投影列),可以通过如下接口设置返回一列或者多列: TableQuery select(String... columns);

3. 设置扫描的列和范围

每次查询需要设置查询扫描列,并添加至少一个查询扫描范围,可以是主键或者主键前缀范围,索引或者索引前缀范围,table api 会基于查询扫描范围进行路由选择,避免发送请求到不必要的 observer 节点上,同时查询扫描范围还会被下推到存储,以提升查询执行的性能,添加查询扫描的接口如下:

TableQuery setScanRangeColumns(String... columns);
TableQuery addScanRange(Object start, Object end);
TableQuery addScanRange(Object[] start, Object[] end);
TableQuery addScanRange(Object start, boolean startEquals, Object end, boolean endEquals);
TableQuery addScanRange(Object[] start, boolean startEquals, Object[] end, boolean endEquals);
  1. start:扫描范围的起点
  2. end:扫描范围的终点
  3. startEquals:扫描范围是否包含 start,不带该参数的接口默认是包含
  4. endEquals:扫描范围是否包含 end,不带该参数的接口默认是包含

4. 定义 Filter 条件

通过 compareVal 可以定义某列的过滤条件,compareVal 的定义如下:

public static ObTableValueFilter compareVal(ObCompareOp op, String columnName, Object value)
  • compareOp:比较操作符,目前支持 LT, GT, LE, GE, NE, EQ, IS, IS_NOT 8 种
  • columnName:指定比较的列名
  • value:指定比较值

5. 使用索引

查询默认使用主键索引进行扫描,同时通过显式指定索引名字来使用特定索引,此时查询扫描范围也是索引或者索引前缀的范围。

TableQuery indexName(String indexName);
  • 当使用索引进行扫描的时(主键也可以看作索引),在每个 observer 分区返回的结果集是索引序的,如果查询的扫描范围只涉及到一个分区,那么返回给客户端结果集也是索引序的。
  • 因为当前 Table API 只支持局部索引,所以当查询范围涉及多个分区的时候,无法保证返回给客户端的结果是整体有序的,在(observer 4.1)支持的全局索引可以实现该功能。

6. 指定 Limit

通过 Limit 可以限制返回的结果集行数(limit),以及跳过的结果集行数(offset),类似 SQL 的 limit m, n 语句,通过指定 limit 可以实现分页查询。

TableQuery limit(int limit);
TableQuery limit(int offset, int limit);

7. 扫描顺序

TableQuery scanOrder(boolean forward);

默认情况下,如果不指定 scanOrder,那么默认就是 forward(从前向后)