基于Tablestore的一站式物联网存储解决方案-数据操作篇

简介: ## 前言上一章节介绍了共享充电宝场景的表结构设计。本章节主要为大家介绍如何使用表格存储Tabelstore数据表实现基本数据读写、批量更新,以及利用多元索引特性实现多维度查询功能。## 准备工作- 测试数据说明| 数据表 | 数据表名 | 数据行数 | 说明 || --- | --- | --- | --- || 元数据表 | cabinet | 一千万行 | 模拟一千万台机柜 |

前言

上一章节介绍了共享充电宝场景的表结构设计。本章节主要为大家介绍如何使用表格存储Tabelstore数据表实现基本数据读写、批量更新,以及利用多元索引特性实现多维度查询功能。

准备工作

  • 测试数据说明
数据表 数据表名 数据行数 说明
元数据表 cabinet 一千万行 模拟一千万台机柜
订单数据表 order 五千万行 模拟五千万条订单数据
元数据时序表 cabinet_time 一亿行 模拟跟踪一万台机柜元数据,十分钟上报一次,共一万个时序点。
  • 测试数据导入。这里提供如下两种测试数据导入方式,二选一即可。

    • 通过github下载demo,运行demo生成测试数据,直接写入Tablestore数据表。
说明:Dataworks可用于OSS与Tablestore之间做数据离线迁移。本场景中的迁移脚本可参考 Github中OSStoOTS.txt。关于Dataworks的介绍可参考 MaxCompute官方文档
  • 测试数据样例

数据表读写

在共享充电宝场景中,新增机柜、机柜下线、租借、归还、查看订单这些业务操作映射到数据库操作中均可看作是对数据表中行的新增、删除、更新、读取。数据操作的方法如下:

说明:更多关于基于主键的数据操作请参考 单行数据操作多行数据操作
  • 新增机柜。可看做在元数据表cabinet中新增一行记录。下面提供了控制台操作截图和SDK代码片段。

PutRowRequest putRowRequest = new PutRowRequest();
//指定表名
RowPutChange rowPutChange = new RowPutChange("cabinet");
//指定主键
rowUpdateChange.setPrimaryKey(PrimaryKeyBuilder.createPrimaryKeyBuilder()           .addPrimaryKeyColumn("cabinet_Md5ID",PrimaryKeyValue.fromString(Md5ID))
.addPrimaryKeyColumn("cabinet_ID",PrimaryKeyValue.fromString(ID)).build());
//添加机柜经纬度
rowPutChange.addColumn("cabinet_geo", ColumnValue.fromString(geo));
//添加机柜位置
rowPutChange.addColumn("cabinet_location",ColumnValue.fromString(position));
//添加机柜所在省份
rowPutChange.addColumn("cabinet_province",ColumnValue.fromString(province));
putRowRequest.setRowChange(rowPutChange);
//发起新增请求
client.putRow(putRowRequest);
  • 租借充电宝。可看做两个步骤。1、订单数据表order写入一条记录。2、更新元数据表cabiet对应的机柜元数据信息。这里主要介绍更新元数据表的操作步骤。
注意:只可对属性列的值进行更新,主键值无法更新。
UpdateRowRequest updateRowRequest = new UpdateRowRequest();
//指定表名 
RowUpdateChange rowUpdateChange = new RowUpdateChange("cabinet");
//指定主键
rowUpdateChange.setPrimaryKey(PrimaryKeyBuilder.createPrimaryKeyBuilder()           .addPrimaryKeyColumn("cabinet_Md5ID",PrimaryKeyValue.fromString(Md5ID))
.addPrimaryKeyColumn("cabinet_ID",PrimaryKeyValue.fromString(ID)).build());
//更新可用充电宝数量
rowUpdateChange.put("cabinet_available_size",ColumnValue.fromLong(availableSize));
//更新机柜电量
rowUpdateChange.put("cabinet_powerPercent",ColumnValue.fromLong(powerPercent));
updateRowRequest.setRowChange(rowUpdateChange);
//发起更新请求
client.updateRow(updateRowRequest);
  • 查看订单。根据订单Md5ID,订单ID查看订单详情。

GetRowRequest getRowRequest = new GetRowRequest();
//指定表名
SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("order");
//指定主键
criteria.setPrimaryKey(PrimaryKeyBuilder.createPrimaryKeyBuilder()              .addPrimaryKeyColumn("order_Md5ID",PrimaryKeyValue.fromString(orderMd5ID))
.addPrimaryKeyColumn("order_ID",PrimaryKeyValue.fromString(orderID)).build());
//指定读取的版本数
criteria.setMaxVersions(1);
getRowRequest.setRowQueryCriteria(criteria);
//发起查询请求
clinet.getRow(getRowRequest);

上面介绍了数据新增、数据更新、数据查询的操作步骤。可以看出,上述操作均是基于主键的,无论是更新或者是查询,都需要传入完整的主键信息。然而在共享充电宝场景中,许多业务需求是要根据属性列作为查询条件来进行筛选。所以,仅仅依靠主键的读写并不能完全满足业务需求,还需要依赖索引能力。下面将为大家介绍Tablestore功能之一多元索引。

多元索引操作

什么是多元索引

多元索引是表格存储Tablestore的功能之一。多元索引基于倒排索引、列式存储,可满足多列自由组查询等复杂查询需求。不同于传统数据库MySQL的索引使用方式,没有最左匹配原则的限制,可灵活地在任意列上建立索引,将查询能力扩展到属性列上,实现对百亿数据毫秒级查询。

创建多元索引

  • 控制台创建步骤
  1. 进入表管理-索引管理页面。点击创建多元索引。
小技巧:多元索引创建后,即可在控制台上看到数据表实时的总行数。
  1. 输入索引名。添加多个索引字段。点击确定。

  • SDK创建代码片段。
说明: 更多关于多元索引创建SDK示例请参考官网文档 创建多元索引
//这里为部分列创建索引
CreateSearchIndexRequest csir = new CreateSearchIndexRequest();
csir.setTableName("cabinet");//设置表名
csir.setTableName("cabinet_index_1");//设置索引名
IndexSchema indexSchema = new IndexSchema();
indexSchema.setFieldSchemas(Arrays.asList(
    new FieldSchema("cabinet_Md5ID", FieldType.KEYWORD),//指定字段名和字段类型
    new FieldSchema("cabinet_ID", FieldType.KEYWORD),
    new FieldSchema("cabinet_available_size", FieldType.LONG),
    new FieldSchema("cabinet_location", FieldType.KEYWORD),
    new FieldSchema("cabinet_geo", FieldType.GEO_POINT),
    new FieldSchema("cabinet_pricePerHour", FieldType.DOUBLE),
    new FieldSchema("cabinet_isonline", FieldType.KEYWORD)
));
csir.setIndexSchema(indexSchema);//设置索引schema
//发送创建多元索引请求
client.createSearchIndex(csir);

多元索引查询

多元索引可实现丰富的查询方式,例如全文检索、前缀查询、模糊查询、组合查询、地理位置查询等等功能。下面以共享充电宝场景中具体的查询需求为例,模拟四个业务场景介绍多元索引的几个重要功能:多字段排序、多字段组合查询、分组聚合等。

  • 场景一。用户需要查询有可租用充电宝的机柜信息,并先按照距离远近倒序排序,再按照机柜时价倒序排序。

查询代码

//场景一。用户需要查询有可租用充电宝的机柜信息,并先按照距离远近倒序排序,再按照机柜时价倒序排序。
    public void searchDemo01(SyncClient client){
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName(Config.CABINET_TABLENAME)//设置表名
                .indexName(Config.CABINET_TABLENAME_INDEX)//设置多元索引名
                .searchQuery(SearchQuery.newBuilder()
                        .query(QueryBuilders.bool()
                                .must(QueryBuilders.range("cabinet_available_size").greaterThan(0))//可用充电宝个数>0
                                .must(QueryBuilders.range("cabinet_powerPercent").greaterThan(50))//电量>50
                               .must(QueryBuilders.term("cabinet_isonline","online"))//状态=在线
                        )
                        .sort(new Sort(Arrays.asList(
                                new GeoDistanceSort("cabinet_geo",Arrays.asList("30.17110,120.29937")),//先按照距离远近升序
                                new FieldSort("cabinet_pricePerHour", SortOrder.ASC)//再按照价格升序
                        )))
                        .build())
                .addColumnsToGet(Arrays.asList("cabinet_manufacturers","cabinet_type","cabinet_pricePerHour","cabinet_location"))//指定返回哪些字段
                .build();
        SearchResponse response = client.search(searchRequest);
        System.out.println(response.getRows());
    }

返回结果

  • 场景二。用户需要查询租赁时价在2元/小时之内,并且有可租用充电宝的机柜。按照距离远近排序。

查询代码

//场景二。用户需要查询租赁时价在2元/小时之内,并且有可租用充电宝的机柜。按照距离远近排序。
    public static void searchDemo02(SyncClient client){
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName(Config.CABINET_TABLENAME)//设置表名
                .indexName(Config.CABINET_TABLENAME_INDEX)//设置多元索引名
                .searchQuery(SearchQuery.newBuilder()
                        .query(QueryBuilders.bool()
                                .must(QueryBuilders.range("cabinet_pricePerHour").greaterThan(0).lessThanOrEqual(2))//时价在0-2元内
                                .must(QueryBuilders.range("cabinet_available_size").greaterThan(0))//可用充电宝个数>0
                                .must(QueryBuilders.term("cabinet_isonline","online"))//状态=在线
                        )
                        .sort(new Sort(Arrays.asList(
                                new GeoDistanceSort("cabinet_geo",Arrays.asList("30.17110,120.29937"))//按照距离远近升序
                        )))
                        .build())
                .addColumnsToGet(Arrays.asList("cabinet_manufacturers","cabinet_type","cabinet_pricePerHour","cabinet_location"))//指定返回哪些字段
                .build();
        SearchResponse response = client.search(searchRequest);
        System.out.println(response.getRows());
    }

返回结果

  • 场景三。运维人员需要查询浙江省内,机柜检修时间戳在半年之前,或者已经下线的机柜。取十条记录。

查询代码

//场景三。运维人员需要查询浙江省内,机柜检修时间戳在半年之前或者已经下线的机柜。取十条记录。
    public static void searchDemo03(SyncClient client){
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName(Config.CABINET_TABLENAME)//设置表名
                .indexName(Config.CABINET_TABLENAME_INDEX)//设置多元索引名
                .searchQuery(SearchQuery.newBuilder()
                        .query(QueryBuilders.bool()
                                .must(QueryBuilders.term("cabinet_province","浙江省"))
                                .must(QueryBuilders.bool()
                                        .should(QueryBuilders.range("cabinet_overhaul_time").lessThan(2592000000L))
                                        .should(QueryBuilders.term("cabinet_isonline","offline"))
                                .minimumShouldMatch(1)
                        ))
                        .limit(10)
                        .sort(new Sort(Arrays.asList(
                                new GeoDistanceSort("cabinet_geo",Arrays.asList("30.17110,120.29937"))//按照距离远近升序
                        )))
                        .build())
                .addColumnsToGet(Arrays.asList("cabinet_manufacturers","cabinet_type","cabinet_pricePerHour","cabinet_location"))//指定返回哪些字段
                .build();
        SearchResponse response = client.search(searchRequest);
        System.out.println(response.getRows());
    }

返回结果

  • 场景四。运维人员需要统计每个省份已经上线的机柜个数,并按照机柜型号分组,取出前五个型号的数据。

查询代码

//场景四。运维人员需要统计每个省份已经上线的机柜个数,并按照机柜型号分组,取出前五个型号的数据。
    public static void searchDemo04(SyncClient client){
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName(Config.CABINET_TABLENAME)//设置表名
                .indexName(Config.CABINET_TABLENAME_INDEX)//设置多元索引名
                .searchQuery(SearchQuery.newBuilder()
                        .query(QueryBuilders.matchAll())
                        .addGroupBy(GroupByBuilders.groupByField("groupByProvince","cabinet_province")
                                .addSubGroupBy(GroupByBuilders.groupByField("groupByType","cabinet_type").size(5)))
                        .build())
                .build();
        SearchResponse searchResponse = client.search(searchRequest);
        List<GroupByFieldResultItem> list = searchResponse.getGroupByResults().getAsGroupByFieldResult("groupByProvince").getGroupByFieldResultItems();
        for(GroupByFieldResultItem groupByFieldResultItem : list){
            System.out.println("省份:【"+groupByFieldResultItem.getKey()+"】 机柜数量:【"+groupByFieldResultItem.getRowCount()+"】");
            List<GroupByFieldResultItem> subList = groupByFieldResultItem.getSubGroupByResults().getAsGroupByFieldResult("groupByType").getGroupByFieldResultItems();
            for(GroupByFieldResultItem subItem : subList){
                System.out.println("型号:"+subItem.getKey()+",机柜数量:"+subItem.getRowCount());
            }
        }
    }

返回结果

SQL操作

可通过
可通过表格存储控制台进行SQL查询,关于表格存储SQL相关操作请参考文档表格存储SQL

创建数据表映射关系

  1. 进入表格存储控制台,实例管理-SQL查询页面。点击一键生成映射关系。

  1. 选择需要映射的表,点击生成SQL。

  1. 执行SQL,得到cabinet、cabinet_time、order三张表的映射。

DML操作示例

  • 场景一。用户需要查询有可租用充电宝的机柜信息,按照机柜时价倒序排序,取前100条。
select * from cabinet where
cabinet_isonline = "online" and
cabinet_available_size > 0 and
cabinet_powerPercent > 50 
order by cabinet_pricePerHour asc limit 100;

  • 用户需要查询租赁时价在2元/小时之内,并且有可租用充电宝的机柜,取100条。
select * from cabinet where cabinet_pricePerHour between 0 and 2 
and cabinet_available_size > 0 and cabinet_isonline = 'online' limit 100;

  • 运维人员需要查询浙江省内,机柜检修时间戳在半年之前,或者已经下线的机柜。取十条记录
select * from cabinet where 
(cabinet_province = '浙江省' and cabinet_overhaul_time < 2592000000) 
or cabinet_isonline = 'offline' limit 10;

  • 运维人员需要统计每个省份已经上线的机柜个数,并按照机柜型号分组
select cabinet_province,cabinet_type,count(*) cabinet_count,any_value(cabinet_Md5ID)
from cabinet
where cabinet_isonline = 'online' 
group by cabinet_province,cabinet_type order by cabinet_count

小结

表格存储Tablestore实现了表引擎和多元索引引擎。其中表引擎可以基于主键实现高并发数据读写,可满足元数据并发更新、订单数据新增等业务。多元索引引擎则提供了多字段组合查询、排序、统计聚合等功能,可在毫秒延迟内对百亿级元数据进行检索、轻量级分析。下一章节将为大家介绍如何通过Spark访问Tablestore实现离线流批计算。

联系我们

如对本章节所述有疑问或有其他问题需要咨询,欢迎加入钉钉群:“表格存储公开交流群-2”。群内提供免费的在线专家服务,欢迎扫码加入,群号23307953。

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
3月前
|
物联网 数据管理 Apache
拥抱IoT浪潮,Apache IoTDB如何成为你的智能数据守护者?解锁物联网新纪元的数据管理秘籍!
【8月更文挑战第22天】随着物联网技术的发展,数据量激增对数据库提出新挑战。Apache IoTDB凭借其面向时间序列数据的设计,在IoT领域脱颖而出。相较于传统数据库,IoTDB采用树形数据模型高效管理实时数据,具备轻量级结构与高并发能力,并集成Hadoop/Spark支持复杂分析。在智能城市等场景下,IoTDB能处理如交通流量等数据,为决策提供支持。IoTDB还提供InfluxDB协议适配器简化迁移过程,并支持细致的权限管理确保数据安全。综上所述,IoTDB在IoT数据管理中展现出巨大潜力与竞争力。
104 1
|
3月前
|
存储 传感器 监控
理解并利用物联网(IoT)数据的技术探索
【8月更文挑战第11天】物联网数据是数字化转型的重要资源。通过深入理解物联网数据的特性和价值,并采取有效的收集、处理和分析策略,我们可以更好地利用这些数据为企业决策提供支持、优化运营效率、创造新的商业模式并推动数字化转型的深入发展。
|
4月前
|
物联网
好的资源链接,gitee全糖咖啡,B站视频转成mp4,全糖咖啡 / 物联网网关数据上传,,全糖咖啡 / springboot+百度智能车牌检测
好的资源链接,gitee全糖咖啡,B站视频转成mp4,全糖咖啡 / 物联网网关数据上传,,全糖咖啡 / springboot+百度智能车牌检测
|
5月前
|
机器学习/深度学习 传感器 算法
物联网(IoT)数据与机器学习的结合
【6月更文挑战第6天】物联网和机器学习加速融合,驱动数据收集与智能分析。通过机器学习算法处理 IoT 数据,实现智能家居、工业生产的智能化。示例代码展示如何用线性回归预测温度。结合带来的优势包括实时监测、预警、资源优化,但也面临数据质量、隐私安全、算法选择等挑战。未来需强化技术创新,应对挑战,推动社会智能化发展。
155 0
|
5月前
|
存储 安全 算法
物联网中的数据加密技术
【6月更文挑战第1天】物联网中的数据加密技术
624 0
|
21天前
|
存储 供应链 物联网
探索未来:区块链、物联网与虚拟现实技术的融合与创新
【10月更文挑战第15天】本文深入探讨了新兴技术如区块链、物联网(IoT)和虚拟现实(VR)的发展趋势及其在现代社会的应用。通过分析这些技术的独特属性和它们如何相互补充,我们揭示了一个由高度互联、智能化和沉浸式体验定义的未来图景。文章不仅讨论了这些技术当前的挑战,还展望了它们在未来可能带来的转变,旨在为读者提供对这些令人兴奋的技术趋势的全面理解。
|
21天前
|
安全 物联网 区块链
未来已来:探索区块链技术、物联网与虚拟现实的融合趋势
【10月更文挑战第15天】 在数字化浪潮中,区块链、物联网(IoT)和虚拟现实(VR)技术正引领着一场革命。本文将深入探讨这三种技术的发展趋势和相互融合的潜力,以及它们如何共同塑造我们的未来。我们将从基本概念入手,逐步揭示这些技术如何影响经济、社会和日常生活,同时提供具体应用场景以展示其变革力量。
|
8天前
|
供应链 物联网 区块链
未来已来:区块链技术、物联网与虚拟现实的融合与创新
【10月更文挑战第28天】在数字化浪潮的推动下,新兴技术如区块链、物联网(IoT)和虚拟现实(VR)正逐步渗透至我们的日常生活中。本文将探讨这些技术的发展趋势,以及它们如何相互融合,创造出前所未有的应用场景。我们将通过实际案例,展示这些技术如何改变工业、医疗、教育和娱乐等多个领域。最后,我们将展望这些技术未来的发展方向,以及它们可能带来的社会变革。
33 12
|
2天前
|
供应链 物联网 区块链
未来已来:探索区块链、物联网与虚拟现实技术的融合趋势与实践应用
【10月更文挑战第34天】随着科技的迅猛发展,新兴技术如区块链、物联网(IoT)和虚拟现实(VR)正逐步渗透到我们的生活中,不仅改变着我们的生活方式,还在重塑全球的经济结构。本文将深入探讨这些技术的发展现状、相互之间的融合趋势以及在实际应用中的创新场景。我们将通过具体案例分析,揭示这些技术如何共同作用,推动社会向更加智能、互联的方向发展。
13 3
|
3天前
|
传感器 监控 物联网
物联网与虚拟现实:未来技术趋势与应用
随着科技的不断进步,新兴技术如物联网(IoT)和虚拟现实(VR)正在逐步改变我们的生活、工作以及娱乐方式。本文旨在探讨这些前沿技术的发展趋势及其在多个行业的潜在应用场景,分析其对社会发展的深远影响,并对未来的发展方向进行展望。通过详细分析,本文揭示了物联网和虚拟现实如何共同推动社会进步,并带来创新和可能性。

热门文章

最新文章

相关产品

  • 物联网平台
  • 下一篇
    无影云桌面