基于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
目录
相关文章
|
1月前
|
传感器 机器学习/深度学习 存储
物联网设备精细化管理系统解决方案
随着科技的进步,物联网技术作为新一代信息技术的核心部分,正在深刻改变各行业的生产和管理方式。其在资产管理、智慧城市、能源管理和智慧医疗等多个领域的广泛应用,不仅提高了运营效率,还促进了资源优化配置和精细化管理。本文详细介绍了物联网的基础概念及其在设备精细化管理系统中的具体应用方案,展示了如何通过智能感知层建设、数据处理分析平台以及精细化管理应用,实现设备的实时监控、预测性维护和能耗管理等功能,从而帮助企业提升竞争力,降低成本,并推动社会向更智能化、绿色化的方向发展。
85 2
物联网设备精细化管理系统解决方案
|
1月前
|
存储 监控 物联网
医疗物联网设备精细化管理系统解决方案
华汇数据智慧医院物联网管理系统解决方案是一种集物联网、云计算、大数据和人工智能等先进技术于一体的综合性解决方案,旨在提升医院的运营效率、医疗质量和患者满意度。
75 3
|
1月前
|
存储 边缘计算 物联网
阿里云物联网平台:推动万物互联的智能化解决方案
随着物联网技术的快速发展,阿里云物联网平台为企业提供了一体化的解决方案,包括设备接入、数据管理和智能应用等核心功能。平台支持海量设备接入、实时数据采集与存储、边缘计算,并具备大规模设备管理、高安全性和开放生态等优势。广泛应用于智能制造、智慧城市和智能家居等领域,助力企业实现数字化转型。
188 5
|
2月前
|
存储 安全 物联网
.NET 跨平台工业物联网网关解决方案
【9月更文挑战第28天】本文介绍了利用 .NET 构建跨平台工业物联网网关的解决方案。通过 .NET Core 和多种通信协议(如 MQTT 和 Modbus),实现工业设备的高效接入和数据采集。系统架构包括设备接入层、数据处理层、通信层、应用层和数据库层,确保数据的准确采集、实时处理和安全传输。此外,还详细阐述了设备身份认证、数据加密及安全审计等机制,确保系统的安全性。该方案适用于不同操作系统和工业环境,具备高度灵活性和扩展性。
|
存储 索引
表格存储根据多元索引查询条件直接更新数据
表格存储是否可以根据多元索引查询条件直接更新数据?
113 3
|
SQL NoSQL 数据可视化
玩转Tablestore:使用Grafana快速展示时序数据
Grafana 是一款采用 go 语言编写的开源应用,主要用于大规模指标数据的可视化展现,是网络架构和应用分析中最流行的时序数据展示工具,可以通过将采集的数据查询然后可视化的展示,实现报警通知;Grafana拥有丰富的数据源,官方支持以下数据源:Graphite,Elasticsearch,InfluxDB,Prometheus,Cloudwatch,MySQ
1755 0
玩转Tablestore:使用Grafana快速展示时序数据
|
4月前
|
DataWorks NoSQL 关系型数据库
DataWorks产品使用合集之如何从Tablestore同步数据到MySQL
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
|
6月前
|
分布式计算 DataWorks API
DataWorks常见问题之按指定条件物理删除OTS中的数据失败如何解决
DataWorks是阿里云提供的一站式大数据开发与管理平台,支持数据集成、数据开发、数据治理等功能;在本汇总中,我们梳理了DataWorks产品在使用过程中经常遇到的问题及解答,以助用户在数据处理和分析工作中提高效率,降低难度。
|
6月前
|
DataWorks NoSQL 关系型数据库
可以使用dataworks从tablestore同步数据到mysql吗?
可以使用dataworks从tablestore同步数据到mysql吗?
75 1
|
NoSQL 开发工具
TableStore表格存储(阿里云OTS)多行数据操作查询,支持倒序,过滤条件和分页
1. 批量读取操作 批量读取操作可以通过多种方式进行,包括: GetRow:根据主键读取一行数据。 BatchGetRow:批量读取多行数据。 GetRange:根据范围读取多行数据。
883 0

相关产品

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