二级索引支持在指定列上建立索引,生成的索引表中的数据按照指定的索引列进行排序,数据表的每一个数据写入都会自动同步到索引表中。您只需向数据表中写入数据,然后根据索引表进行查询,在许多场景下能提高查询的效率。
样例场景
在电话话单查询场景下,每次用户通话结束后,都会将此次通话的信息记录到该数据表中。
数据表的主键和预定义列如下:
CellNumber、StartTime作为数据表的主键,分别代表主叫号码和通话发生时间。
CalledNumber、Duration和BaseStationNumber为数据表的预定义列,分别代表被叫号码、通话时长和基站号码。
数据表的样例数据请参见下表。表格存储的宽表模型是对所有行按照主键进行排序,并且提供顺序扫描(GetRange)接口用于数据读取。
CellNumber | StartTime(Unix时间戳) | CalledNumber | Duration | BaseStationNumber |
123456 | 1532574644 | 654321 | 60 | 1 |
234567 | 1532574714 | 765432 | 10 | 1 |
234567 | 1532574734 | 123456 | 20 | 3 |
345678 | 1532574795 | 123456 | 5 | 2 |
345678 | 1532574861 | 123456 | 100 | 2 |
456789 | 1532584054 | 345678 | 200 | 3 |
假设如下查询需求,请根据实际情况通过数据表、全局二级索引或者本地二级索引查询所需数据。
查询号码234567的所有主叫话单
查询号码123456的被叫话单
查询基站002从时间1532574740开始的所有话单
查询发生在基站003上时间从1532574861到1532584054的所有通话记录的通话时长
查询发生在基站003上时间从1532574861到1532584054的所有通话记录的总通话时长、平均通话时长、最大通话时长和最小通话时长
查询主叫号码456789到被叫号码345678的所有话单
数据查询
请根据查询需求选择合适的查询方式。
实现方式
不同查询需求的具体实现方式请参见下表说明。
关于创建表和二级索引的示例请参见附录:创建数据表和二级索引示例。
创建数据表后需要写入样例数据到数据表,数据表中的数据会自动同步到索引表中。关于写入数据的具体操作,请参见写入数据。
系统会自动进行索引列补齐,即把数据表的主键添加到索引列后,共同作为索引表的主键。
本地二级索引的第一个主键列必须与数据表的第一个主键列相同。
查询需求 | 实现方式 |
查询号码234567的所有主叫话单 | 直接调用getRange接口对数据表进行扫描。 |
查询号码123456的被叫话单 | 在CalledNumber列上建立索引,然后调用getRange接口对索引表进行扫描。 |
查询基站002从时间1532574740开始的所有话单 | 在BaseStationNumber和StartTime列上建立组合索引,然后调用getRange接口对索引表(全局二级索引)进行扫描。 |
查询发生在基站003上时间从1532574861到1532584054的所有通话记录的通话时长 | 在BaseStationNumber和StartTime列上建立组合索引,而且只把Duration列作为返回结果,然后调用getRange接口对索引表(全局二级索引)进行扫描。 您可以手动反查数据表获取Duration列值或者将Duration列作为索引表的属性列。 如果要查询发生在基站003上时间从1532574861到1532584054的所有通话记录的总通话时长、平均通话时长、最大通话时长和最小通话时长,您可以使用与本查询需求相同的实现方式,然后对返回的每条通话时长做计算并得到最终结果。 说明 您也可以使用表格存储SQL查询,无需客户端计算,直接使用SQL语句返回最终统计结果。更多信息,请参见查询数据。 |
查询主叫号码456789到被叫号码345678的所有话单 | 在CellNumber列和CalledNumber列上建立组合索引,而且将Duration列和BaseStationNumber列作为索引表的属性列,然后调用getRange接口对索引表(本地二级索引)进行扫描。 |
查询号码234567的所有主叫话单
查询号码123456的被叫话单
查询基站002从时间1532574740开始的所有话单
查询发生在基站003上时间从1532574861到1532584054的所有通话记录的通话时长
查询主叫号码456789到被叫号码345678的所有话单
附录:创建数据表和二级索引示例
以下示例用于创建本文中用到的数据表和二级索引(包括本地二级索引和全局二级索引)。
private static final String TABLE_NAME = "CallRecordTable";
private static final String INDEX0_NAME = "IndexOnBeCalledNumber";
private static final String INDEX1_NAME = "IndexOnBaseStation1";
private static final String INDEX2_NAME = "IndexOnBaseStation2";
private static final String INDEX3_NAME = "LocalIndexOnBeCalledNumber";
private static final String PRIMARY_KEY_NAME_1 = "CellNumber";
private static final String PRIMARY_KEY_NAME_2 = "StartTime";
private static final String DEFINED_COL_NAME_1 = "CalledNumber";
private static final String DEFINED_COL_NAME_2 = "Duration";
private static final String DEFINED_COL_NAME_3 = "BaseStationNumber";
private static void createTable(SyncClient client) {
TableMeta tableMeta = new TableMeta(TABLE_NAME);
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY_NAME_1, PrimaryKeyType.INTEGER));
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY_NAME_2, PrimaryKeyType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_1, DefinedColumnType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_2, DefinedColumnType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_3, DefinedColumnType.INTEGER));
//数据的过期时间, 单位秒, -1代表永不过期. 带索引表的主表数据过期时间必须为-1。
int timeToLive = -1;
//保存的最大版本数, 带索引表的主表最大版本数必须为1。
int maxVersions = 1;
TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
ArrayList<IndexMeta> indexMetas = new ArrayList<IndexMeta>();
IndexMeta indexMeta0 = new IndexMeta(INDEX0_NAME);
indexMeta0.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
indexMetas.add(indexMeta0);
IndexMeta indexMeta1 = new IndexMeta(INDEX1_NAME);
indexMeta1.addPrimaryKeyColumn(DEFINED_COL_NAME_3);
indexMeta1.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
indexMetas.add(indexMeta1);
IndexMeta indexMeta2 = new IndexMeta(INDEX2_NAME);
indexMeta2.addPrimaryKeyColumn(DEFINED_COL_NAME_3);
indexMeta2.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
indexMeta2.addDefinedColumn(DEFINED_COL_NAME_2);
indexMetas.add(indexMeta2);
IndexMeta indexMeta3 = new IndexMeta(INDEX3_NAME);
indexMeta3.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
indexMeta3.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
indexMeta3.addDefinedColumn(DEFINED_COL_NAME_2);
indexMeta3.addDefinedColumn(DEFINED_COL_NAME_3);
//设置索引同步模式。
indexMeta3.setIndexUpdateMode(IUM_SYNC_INDEX);
//设置索引类型为IT_LOCAL_INDEX(本地二级索引)。
indexMeta3.setIndexType(IT_LOCAL_INDEX);
indexMetas.add(indexMeta3);
CreateTableRequest request = new CreateTableRequest(tableMeta, tableOptions, indexMetas);
client.createTable(request);
}