Tablestore入门手册--全局二级索引使用
Tablestore入门手册--全局二级索引使用
概述
全局二级索引和主表有着相同的存储结构,其索引列可以是主表的主键列或预定义列,其属性列为主表的预定义列。写入主表的数据,经过毫秒级延迟异步同步到全局二级索引,即可被查到。
与主表相同,如GetRow,BatchGetRow和BatchGetRow的查询操作均可以作用于二级索引;与主表不同,二级索引不支持用户直接写,只接受来自主表的数据同步。
指定主键的前缀范围,可以实现对主表的范围扫描(GetRange),查询范围的指定必须和主键范围保持一致。如果查询范围无法表示成主键前缀的形式,则可以使用二级索引重新组合字段顺序。相比范围查询(GetRange)加过滤器(filter)的方式,二级索引可以大大减少扫描数据量,提升查询速度。
本文通过一个例子来阐述二级索引加速查询的本质,使用姿势,并配上完整代码——
以电话话单查询为背景,用户的每次通话,都会被记录在如下主表中:
CellNumber、StartTime作为表的联合主键,分别代表主叫号码与通话发生时间。
CalledNumber、Duration、BaseStationNumber三列为表的预定义列,分别代表被叫号码、通话时长、基站号码。
假想两个查询场景:
查询1:查询号码234567的主叫话单
GetRange直接查询主表即可——指定CellNumber最小值和最大值均为234567;指定StartTime最小值为0,最大值为INT_MAX。
查询2:查询号码123456的被叫话单,并返回基站号码
如果直接查询主表,必须扫描全表,再过滤出被叫号码CalledNumber为123456的行,性能差,成本高。此时,您可以创建一张全局二级索引表,具体做法如下——
- 全局二级索引schema
将被叫号码CalledNumber放在二级索引表的pk列(系统会自动追加主表pk列补全索引表pk列,保证行的唯一性)。查询要求返回基站号码BaseStationNumber,可以将这一列设置为索引表的属性列,否则还要用索引表查询得到的pk反查主表。因此,二级索引的shema如下所示。
其中,CalledNumber是用户指定的索引pk列;CellNumber和StartTime是系统自动补全的索引pk列。
- 查询全局二级索引
指定主键前缀范围CalledNumber从123456到123456,CellNumber从INT_MIN到INT_MAX,StartTime从INT_MIN到INT_MAX,使用GetRange查询索引表,并指定返回列包含基站号码。
下面来看看创建、查询以及删除全局二级索引的主要代码。
创建
创建分两种方式,效果等价。
方式一:创建主表的同时创建全局二级索引表
//二级索引IndexMeta IndexMeta indexMeta = new IndexMeta(indexName); indexMeta.addPrimaryKeyColumn(CALLED_NUMBER); //将主表的预定义列"called_number"作为二级索引表的pk列 //此时会自动补齐二级索引表的剩余两个pk列: "cell_number", "start_time" indexMeta.addDefinedColumn(BASE_STATION_NUMBER); //将主表的预定义列"base_station_number"作为二级索引表的属性列 //创建主表时,同时创建索引表 TableMeta tableMeta = new TableMeta(tableName); tableMeta.addPrimaryKeyColumn(CELL_NUMBER, PrimaryKeyType.INTEGER); tableMeta.addPrimaryKeyColumn(START_TIME, PrimaryKeyType.INTEGER); tableMeta.addDefinedColumn(new DefinedColumnSchema(CALLED_NUMBER, DefinedColumnType.INTEGER)); tableMeta.addDefinedColumn(new DefinedColumnSchema(BASE_STATION_NUMBER, DefinedColumnType.INTEGER)); TableOptions tableOptions = new TableOptions(-1, 1); CreateTableRequest createTableRequest = new CreateTableRequest(tableMeta, tableOptions, Arrays.asList(indexMeta)); syncClient.createTable(createTableRequest);
方式二:先创建主表;再为已经存在的主表添加二级索引表
- 创建主表
TableMeta tableMeta = new TableMeta(tableName); tableMeta.addPrimaryKeyColumn(CELL_NUMBER, PrimaryKeyType.INTEGER); tableMeta.addPrimaryKeyColumn(START_TIME, PrimaryKeyType.INTEGER); tableMeta.addDefinedColumn(new DefinedColumnSchema(CALLED_NUMBER, DefinedColumnType.INTEGER)); tableMeta.addDefinedColumn(new DefinedColumnSchema(BASE_STATION_NUMBER, DefinedColumnType.INTEGER)); // Set TTL to -1, never expire; Set maxVersions to 1, as one version is permitted TableOptions tableOptions = new TableOptions(-1, 1); CreateTableRequest createTableRequest = new CreateTableRequest(tableMeta, tableOptions); syncClient.createTable(createTableRequest);
- 创建二级索引
includeBaseData可以指定索引的同步方式。
true表示:创建索引前主表的存量数据,也会被同步到索引表中;
false则表示:只会同步创建索引后主表的增量数据。
IndexMeta indexMeta = new IndexMeta(indexName); indexMeta.addPrimaryKeyColumn(CALLED_NUMBER); //将主表的预定义列"called_number"作为二级索引表的pk列 //此时会自动补齐二级索引表的剩余两个pk列: "cell_number", "start_time" indexMeta.addDefinedColumn(BASE_STATION_NUMBER); //将主表的预定义列"base_station_number"作为二级索引表的属性列 //全局二级索引索引创建请求(includeBaseData为true表示先同步主表全量数据,再同步增量数据; includeBaseData为false表示只同步增量数据) CreateIndexRequest request = new CreateIndexRequest(tableName, indexMeta, true); //创建全局二级索引 syncClient.createIndex(request);
查询
查询二级索引使用和查询主表一样的方式。在这个例子中,用户指定二级索引pk列为CalledNumber,系统会自动补齐剩余两列主键列CellNumber和StartTime。创建二级索引时,指定预定义列BaseStationNumber为属性列,因此直接查询索引即可返回“基站号码”信息,无需反查主表。但如果要返回通话时长Duration列,则需要先查询二级索引返回主键列,再用主键列反查主表。
本例中,查询号码123456的被叫话单,并返回基站号码可以这样写:
RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria(indexName); long calledNumber = 123456L; // 构造主键 PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); startPrimaryKeyBuilder.addPrimaryKeyColumn(CALLED_NUMBER, PrimaryKeyValue.fromLong(calledNumber)); startPrimaryKeyBuilder.addPrimaryKeyColumn(CELL_NUMBER, PrimaryKeyValue.INF_MIN); startPrimaryKeyBuilder.addPrimaryKeyColumn(START_TIME, PrimaryKeyValue.INF_MIN); rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build()); // 构造主键 PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder(); endPrimaryKeyBuilder.addPrimaryKeyColumn(CALLED_NUMBER, PrimaryKeyValue.fromLong(calledNumber)); endPrimaryKeyBuilder.addPrimaryKeyColumn(CELL_NUMBER, PrimaryKeyValue.INF_MAX); endPrimaryKeyBuilder.addPrimaryKeyColumn(START_TIME, PrimaryKeyValue.INF_MAX); rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build()); rangeRowQueryCriteria.setMaxVersions(1); rangeRowQueryCriteria.addColumnsToGet(BASE_STATION_NUMBER); //查询二级索引,返回pk列和属性列"base_station_number" System.out.println(String.format("号码 %d 的所有被叫话单: ", calledNumber)); while (true) { GetRangeResponse getRangeResponse = syncClient.getRange(new GetRangeRequest(rangeRowQueryCriteria)); for (Row row : getRangeResponse.getRows()) { System.out.println(row); } // 若nextStartPrimaryKey不为null, 则继续读取. if (getRangeResponse.getNextStartPrimaryKey() != null) { rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey()); } else { break; } }
列出二级索引
列出一张主表有哪些二级索引。
DescribeTableRequest request = new DescribeTableRequest(tableName); DescribeTableResponse response = syncClient.describeTable(request); for (IndexMeta indexMeta : response.getIndexMeta()) { System.out.println(indexMeta.getIndexName()); }
查询二级索引meta信息
可以如同查询主表meta一样,查询二级索引的meta信息。
DescribeTableResponse response = syncClient.describeTable(new DescribeTableRequest(indexName)); System.out.println(response.getTableMeta());
删除
删除二级索引。
DeleteIndexRequest request = new DeleteIndexRequest(tableName, indexName); syncClient.deleteIndex(request);
代码
完整代码在这里:https://github.com/aliyun/tablestore-examples/tree/master/basic/Java/GlobalIndexCRD
总结
二级索引以另一种顺序重组主表的主键列和预定义列,在特定的场景下,您可以避免大范围的扫描主表,极大提升了查询效率。更多细节可以参考官网文档 https://help.aliyun.com/document_detail/91947.html。
如有疑问或者需要更好的在线支持,欢迎加入钉钉群:“表格存储公开交流群”(群号:23307953)。群内提供免费的在线专家服务,欢迎扫码加入。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
2019百度阿里Java面试题(基础+框架+数据库+分布式+JVM+多线程)
前言 很多朋友对面试不够了解,不知道如何准备,对面试环节的设置以及目的不够了解,因此成功率不高。通常情况下校招生面试的成功率低于1%,而社招的面试成功率也低于5%,所以对于候选人一定要知道设立面试的初衷以及每个环节的意义,有的放矢... 通过现场分析互联网的JD,让面试者掌握分析公司对技术的要求和定位,进而知道自己是否适合该岗位以及应该如何准备。想提高面试成功率一定要了解公司的业务,去分析公司对应业务的站点了解他们使用的技术栈,进而去准备相关的知识,最后一小节关于自我介绍,大多数面试失败都是简历和自我介绍导致的,只是大多数人并不自知。.二面/三面更侧重于对Java知识的深度和广度来进行考察,这个环节不再局限于基础知识,更多的是底层源码、项目实战等方面。 基础与框架 1.String类能被继承吗,为什么2.String,Stringbuffer,StringBuilder的区别?3.ArrayList和LinkedList有什么区别4.类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序5.用过哪些Map,都有什么区别,HashMap是线程安全的...
- 下一篇
quickly 1.3 版本发布,CSS 前端框架
quicklyCSS前端框架发布1.3版本 演示地址 http://qietu.com/quickly-1.3/ pc界面 移动界面 关于框架 quicklyCSS框架曾用名 ThinkCSS,QuickCSS ,是武汉切图网络技术有限公司(简称切图网)基于多年前端外包经验开发的一套快速响应式切图框架。 对比Bootstrap 除了基于12列删格系统,还新增有10列删格系统来满足5等分的布局需求; 兼容性更高; 简化了响应式分段区间,仅为PC和手机两种自适应切换,使用更简单; 更新记录 调整了红蓝黄绿的颜色值,更加鲜亮,符合当下审美; 新增了qui-fill1-5满足多样的删格布局需求; 增加了移动端样式qui-m-col5,qui-m-fs20等满足移动端的删格自定义和字体大小定义等; 重新更新了字体图标来自iconfont; 新增了qui-card卡片样式; 增加了10列删格样式qui-row10,满足5等分布局的需求; 增加了微调的代码qui-mgt10,qui-pdt10,qui-fs20 等等
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合Redis,开启缓存,提高访问速度