通过SQL即可让监控分析更简单更高效

1.前言

阿里时序时空数据库TSDB最新推出TSQL,支持标准SQL的语法和函数。用户使用熟悉的SQL,不仅仅查询更简单易用,用户还可以利用SQL强大的功能,实现更加复杂的计算分析。

2. 为什么需要用SQL做时序查询?

2.1 SQL拥有广泛用户基础

SQL作为一个诞生于上世纪70年代的编程语言已经存在几十年了。这是一个相对而言较“古老”的编程语言,但又是一个有着广泛用户基础的语言。
在跟踪主要编程语言的流行程度的TIOBE index[1]中,SQL在2019年4月份的排名是第8。而如果把排名列在11-20之间的SQL的两个“兄弟”PL/SQL, Transact-SQL也合并进来的话,SQL的流行度应该更高。

 

根据stackoverflow网站的调查 [2],SQL在最流行的编程语言榜上排在第4位。

 

无论TIOBE index还是stackoverflow的编程语言排行榜,都从一个侧面反映了SQL的广泛用户基础。作为一个查询语言,SQL是用户和数据库系统交互的(直接或间接)主要方式。支持一个拥有广泛用户基础的查询语言,对于推广数据库系统来说,是非常重要的。

2.2 用户学习成本

最近几年出现的几个主要面向时序场景的数据库,除了TimescaleDB是在Postgres基础上所以支持PG生态包括SQL语言支持,其他几个比如InfluxDB, OpenTSDB, Prometheus都有各自不同的查询语言和接口:InfluxDB有InfluxQL,OpenTSDB有自己的Restful API, 而Prometheus有PromQL。每一个系统都可以声称自己的语言是独一无二的,更适合时序查询这样的场景;但不可否认的事实是用户需要去花时间去学习一种新的语言,并且如果这个语言为了功能完善,还在不断演进中,这样的学习成本对用户来说,尤其显得高了。
举个例子,InfluxDB的InfluxQL并不支持Join,Subqueries, 以及SQL中很常见的UDF等功能,这意味着用户并不能在不同数据之间进行关联分析计算,也不能在系统函数基础上进行扩展开发。InfluxDB设计者在听到社区的意见后,做了一个很有“创意”的事情:在新版本里支持Join,UDF等功能,但并不是让InfluxQL变得更加接近于SQL,而是在一个全新的Flux(一个新的functional scripting language)里支持 [3]。用户想要做InfluxQL不能做的事情,那就再来学习一个新语言吧。
一个很有意思的事情,10多年前开始出现的NoSQL系统,比如MapReduce/Hadoop, BigTable,Casandra,HBase等,一开始也是以各自不同的查询语言出现的。在经历了多年用户推广之后,NoSQL开始拥抱SQL,变成了NotOnlySQL或者NewSQL。时序数据库这样一个新兴的数据库领域,也有可能重复这样的历史。原因很简单,用户学习一个新语言的成本越高,越会阻碍一个系统被推广到大众接受的程度。

2.3 BI工具生态支持

时序数据库提供SQL的查询支持,一个很重要的原因是将时序数据库的应用场景扩展到商业分析(BI/Business Analysis),商业决策这样高附加值领域。
当前几个主要的时序数据库,包括InfluxDB, OpenTSDB和Prometheus,主要侧重于基础性能监控这样的场景,利用Grafana这样的可视化工具,实现监控报警这一类基本功能。另一方面,监控报警还没有充分利用挖掘时序数据的商业价值。进一步的功能,需要充分利用现有SQL生态系统中的商业分析工具,比如Tableau, Qlik,Oracle BI, IBM Cognos等。这些BI工具,往往是以SQL的方式同后端数据库交互。从这个角度来说,时序数据库的SQL支持对于对接BI生态系统中的各种工具,尤为重要。

2.4 TSQL面向的用户群

在阿里时序数据库TSDB支持的兼容OpenTSDB查询协议之上推出的TSQL查询引擎,主要是面向以下两类用户:

**- 时序数据库TSDB的新应用开发者 
**:这类用户往往以前使用关系数据库,因为关系数据库本身处理时序数据的性能和可扩展性的局限,而转而使用TSDB。这些新应用开发者,希望TSDB在提供比关系数据库更好的时序性能和扩展性的同时,能够用他们以前熟悉的查询语言进行应用开发,而不是去学习一个新的查询语言。
**- 数据分析师:
**这类用户并不开发应用,他们的工作是利用已有的商业分析工具,对时序数据进行进一步的查询分析。他们本身并不直接使用SQL, 但所使用的工具以SQL作为和时序数据库TSDB交互的查询语言。

3. 现有时序数据库系统SQL查询能力比较

这里简单对比时序数据库系统中提供SQL查询,或SQL-like查询能力的InfluxDB, TimescaleDB, 阿里云TSDB。

 

4. TSQL系统架构

 

上图是TSQL的总体架构以及和TSDB引擎和存储之间的协调工作关系。简单来讲,TSQL是一个典型的MPP的SQL分析引擎,通过Connector同TSDB引擎和存储进行数据交换。Connector支持MetaAPI和DataAPI。

TSQL是在两个Apache开源项目基础上演进开发的:

  • Apache Calcite作为SQL的解析器和计划生成和优化器。
  • Apache Drill提供分布式的SQL执行层。
    Apache Calcite作为一个扩展性好,支持标准SQL语法和语义的SQL计划生成器,已经被很多数据处理相关的开源项目使用[6],包括大数据ETL的Apache Hive, HBase上的SQL解决方案Apache Phoenix, 也有流数据处理框架Apache Fink (阿里的Blink)和Apache Beam等。 TSQL使用Calcite作为SQL计划生成器,可以在兼容标准SQL方面,充分利用开源社区已有的成果。

4.1 时序数据Schema管理

InfluxDB, OpenTSDB和Prometheus都采用的是一种Schema-on-write的方式,也就是用户并不需要明确定义metric的schema, 而是将schema的信息隐藏在数据中,在数据写入的时候,同时管理着schema。这样做的好处是更高的灵活性:

  • 在写入数据的时候,用户不需要事先必须用Create Table DDL来创建table;
  • 在时序数据tag set出现变化的时候,用户不需要事先用Alter Table来修改table的schema。

TimeScaleDB从PG上扩展而来,所以是采用的是严格的Schema的管理方式。在使用灵活性方面,不如上面其他3个时序数据库。

Calcite作为一个SQL计划生成器,很适合时序数据库这样的比较松散的Schema管理方式。 Calcite的Schema Adapter,可以支持

  1. 动态的Schema 发现,
  2. 任意一个数据集,只要实现Schema管理中的接口API, 就可以在计划解析生成阶段被当成一个Table来处理。

TSQL在Calcite的Schema Adapter基础上,利用TSDB引擎中新增加的MetaAPI,来完成SQL计划解析和生成。这免去了用户必须事先在一个集中式的catalog中预先定义Table DDL等繁琐工作,给用户带来了很多的灵活性。

4.2 时序数据查询执行

TSQL的执行层,利用了Apache Drill的runtime execution。Drill的runtime execution,具备以下特点

  • 利用off-heap内存作为计算内存,减少Java heap内存GC所带来的延迟问题
  • 基于Columnar格式的ValueVector (Apache Arrow的前身),提升查询执行效率
  • 动态代码生成和编译
    UDF支持

5. TSQL时序查询功能

我们以一个基础性能监控场景来举例说明TSQL能完成的时序查询功能。利用一个时序数据库业界公开的时序性能Benchmark[5] 生成的模拟数据,按照DevOps这样的场景,产生了cpu相关的10不同的metric。每个metric对应了机房(datecenter),主机(hostname),rack等标签下所采集的服务器cpu相关的指标数据。

5.1 元数据查询

可以用下面的方式查询TSDB中所有的metric/table

SHOW TABLES FROM tsdb

如果我们希望列出所有以cpu为前缀的metric/table,可以在上面的查询基础之上添加附带过滤条件.

show TABLES from tsdb where TABLE_NAME like 'cpu%'

下图给出了命令的部分输出:

 

在获得metric/table 名字后,我们可以进一步用SQL中的'DESCRIBE'命令来查询这个metric/table的schema信息

describe tsdb.`cpu.usage_user`

下图显示了上面的'describe'命令的部分结果:

 

5.2 时序数据简单查询

用下面的SQL查询可以获得指定时间段内的'cpu.usage_user'的指标值,时间戳,以及对应的标签值。

select * 
from tsdb.`cpu.usage_user`
where `timestamp`  between '2019-05-01 16:00:00' and '2019-05-01 18:00:00'

这里, 将被转换成 metric/table下所有的列,包括指标值,时间戳,所有的标签列。可以以具体的列名的一个列表来代替。
作为对比,如果把上面的查询转化成OpenTSDB协议来查询,相对应的查询如下:

{"start": "1556726400000","end": "1556733600000","queries": [{"aggregator": "none","metric": "cpu.usage_user","rate": null,"downsample": null,"filters": []}]
}

可以在时间戳的过滤条件基础上,增加指标列上的条件。下面的查询,列出指定时间段内,3台主机上的指标值,并且使用limit, 把查询结果限制在100行。

select * 
from tsdb.`cpu.usage_user`
where `timestamp`  between '2019-05-01 16:00:00' and '2019-05-01 18:00:00'   and hostname in ('host_1', 'host_5', 'host_10')
limit 100

可以在查询中使用标准SQL中丰富的数值计算函数,字符串函数或时间戳函数。下面的SQL,我们分别使用了数值运算函数sqrt, 时间戳函数extract 和字符串lower。

5.3 时序降精度,聚合运算

如果我们要计算两小时之内,每台主机上每5分钟的指标cpu.usage_user的最大值,最小值,以及数据采样点的个数。这样的查询,代表了在时间维度上的降精度,并且在标签hostname上进行的聚合运算。用TSQL来表示这样的查询:

selecthostname,tumble(`timestamp`, interval '5' minute) ts,max(`value`) maxV,min(`value`) minV,count(`value`) cntfrom tsdb.`cpu.usage_user`where `timestamp` between 1556726400000 and 1556733600000   and hostname in ('host_8','host_5','host_6')
group by hostname, ts

如果用OpenTSDB的协议来查询:

{"start": "1556726400000","end": "1556733600000","queries": [{"aggregator": "max","metric": "cpu.usage_user","downsample": "5m-max","tags":{"hostname":"host_8|host_5|host_6"}},{"aggregator": "min","metric": "cpu.usage_user","downsample": "5m-min","tags":{"hostname":"host_8|host_5|host_6"}},{"aggregator": "sum","metric": "cpu.usage_user","rate": null,"downsample": "5m-count","tags":{"hostname":"host_8|host_5|host_6"}}]
}

可以看到,相比较原来Restful API的查询,TSQL能够用更简洁的方式来表示相同的查询语义;并且,如果用户本来就熟悉SQL的使用方法,节省用户去学习Restfule API里JSON各个字段的含义。从降低用户学习成本,增加易用性这个角度,TSQL带来了较明显的价值。

TSQL不仅仅带来查询简洁,用户易用的优点,并且,更重要的是,用TSQL能够表达Restful API里不能直接表达的查询语义。在TSDB引入TSQL之前,如果用户需要进行这样的查询计算,则用户必须通过自己的应用程序,在Restful API获得数据后,再进行后计算,来满足业务需要。在自己的应用程序中进行后计算,往往需要付出很大的应用开发代价。

5.4 聚合后计算,过滤,排序

下面的例子,计算2个小时内,3台机器上每5分钟内,cpu.usage_user指标值的最大值和最小值的差异超过10.0的时段和hostname, 并按照差异值从大到小排序:
在上面的例子中个,在获得最大值和最小值后,进一步计算两者的差异值,并根据差异值进行过滤和排序。这样的聚合后计算处理,无法用OpenTSDB的查询协议表示;用户如果要表达这样的语义,就必须在应用程序中计算。

selecthostname,tumble(`timestamp`, interval '5' minute) ts,max(`value`) - min(`value`) as diffVfrom tsdb.`cpu.usage_user`where `timestamp`  between '2019-05-01 16:00:00' and '2019-05-01 18:00:00'   and hostname in ('host_1', 'host_5', 'host_10')
group by hostname, ts
HAVING  diffV > 10.0
order by diffV DESC

5.5 任意复杂的条件表达式

TSDB的Restful API对于只提供有限的几种filter, 而并不支持任意filter通过AND/OR的组合。比如下面的例子,是一个TSQL业务中使用的查询。其中WHERE条件部分是并不能用Restful API来表示的,因为Restful下的filters是只有AND, 而OR只有在相同tag上通过'value1|value2|vale3'这样的形式来表达。

where((obj_id='ems30_NA62_183249003' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C') or(obj_id='ems30_NA62_183249746' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C') or(obj_id='ems30_NA62_183246962' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C') or(obj_id='ems30_NA62_183248143' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C') or(obj_id='ems30_NA62_183249191' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C') or(obj_id='ems30_NA62_183249964' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C') or(obj_id='ems30_NA62_183247148' and obj_type='ems30_NA62_20204' and room='ems30_NA62_C-T01.NA62' and building='ems30_NA62_C')) and `timestamp` between '2019-04-25 18:20:21' and '2019-04-25 18:20:31'...

支持任意组合的AND/OR的条件表达式,对于应用开发是很有意义的。在集团基础监控业务(raptor-pro)中,一个突出的亮点是“定制化监控报警”:允许业务方的用户来定制查询条件,并且查询条件可以是任意的AND/OR组合。TSQL为"定制化监控报警"的功能实现,提供了有力的技术保障。

5.6 多个metric之间join

这个查询,把cpu.usage_system和cpu.usage_idle在hostname和timestamp上做等值join, 然后计算每5分钟两个度量值之和的sum。

select t1.hostname, tumble(t1.`timestamp`,  interval '5' minute ) ts, sum(t1.`value` + t2.`value`) as sumV
from tsdb.`cpu.usage_system` t1, tsdb.`cpu.usage_idle` t2
where t1.`timestamp` >='2019-05-01' and t1.`timestamp` <= '2019-05-01 01:00:00' and t1.hostname = t2.hostnameand t1.`timestamp`= t2.`timestamp`
group by t1.hostname, ts

上面的查询,如果我们采用TSDB的多值模型,把cpu.usage_system和cpu.usage_idle处理成一个metric的不同的field, 则不需要join就可以完成。但如果我们需要在分组聚合后的结果上再做join, 多值模型也无法解决问题。

5.7 分组聚合后join计算

下面的查询,分别对cpu.usage_system和cpu.usage_idel按照5分钟计算聚合函数sum(), 再通过join, 对齐,计算相对应的比例。并且,每个子查询的Where条件,除了包括在tag上和时间戳上的条件,还包括值上的过滤条件。
类似这样的查询,是无法直接在TSDB的RestAPI来实现的;用户只能在自己的应用程序中实现,增加了应用开发成本。

select f0.hostname, f0.ts, f0.sumV / f1.sumV as resultValue
from (select hostname,tumble(`timestamp`,  interval '5' minute) ts, sum(`value`) as sumVfrom tsdb.`cpu.usage_system`wherehostname in ('host_0', 'host_5', 'host_10') and`timestamp` between '2019-05-01 00:00:00' and '2019-05-01 01:00:00' and `value`<=50group by hostname, ts) as f1
join (select hostname,tumble(`timestamp`,  interval '5' minute ) ts, sum(`value`) as sumVfrom tsdb.`cpu.usage_idle`wherehostname in ('host_0', 'host_5', 'host_10') and`timestamp` between '2019-05-01 00:00:00' and '2019-05-01 01:00:00' and `value`<=30group by hostname, ts) as f0
on f1.hostname = f0.hostname and f1.ts = f0.ts

5.8 UDF扩展功能

使用UDF来扩展功能,对于时序数据库这样聚焦特定领域的数据库来说,是非常必要的,因为往往SQL标准中定义的函数,并不能完全满足需要。TSQL有一个完善的UDF的体系,用户只要按照约定的接口,用Java语义就可以实现扩展。比如,我们在TSQL中引入的把时间戳分割成不重合的窗口的函数tumble,其实现就是由下面不到15行代码完成。
用户可以用Java实现不同的scalar UDF或者aggregate UDF, 并把编译后的jar加入到TSQL的系统类库目录,就可以自行扩展TSQL的查询计算功能了。

@FunctionTemplate(name = "tumble", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.NULL_IF_NULL)public static class Tumble implements DrillSimpleFunc {@Param TimeStampHolder timeStamp;@Param IntervalDayHolder interval;@Output TimeStampHolder out;@Overridepublic void setup() {}@Overridepublic void eval() {long intervalMs = interval.days * org.apache.drill.exec.vector.DateUtilities.daysToStandardMillis + interval.milliseconds;out.value = timeStamp.value - timeStamp.value % intervalMs;}}

6.TSQL可视化查询

阿里云TSDB已经提供了TSQL可视化交互式开发功能,通过web页面可以方便的进行TSQL的测试和开发,如下图Demo所示。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度好文 | 战“疫”上云正当时:打开云计算的正确姿势

作者 | 马超责编 | Carol封图 | CSDN 付费下载于视觉中国4月29日&#xff0c;谷歌的母公司Alphabet正式发布了2020年第一季度财报&#xff0c;报告显示&#xff0c;Alphabet比去年同期的363.39亿美元增长13%&#xff0c;不计入汇率变动的影响为同比增长15%&#xff1b;在业绩公…

Windows批处理文件(.bat文件和.cmd文件)简单使用

cmd文件和bat文件的区别&#xff0c;从文件描述中的区别是&#xff0c;cmd文件叫做&#xff1a;Windows命令脚本&#xff0c;bat文件叫&#xff1a;批处理文件&#xff0c;两者都可以使用任意一款文本编辑器进行创建、编辑和修改&#xff0c;只是在cmd中支持的命令要多于bat。 …

AnalyticDB for MySQL:PB级云数仓核心技术和场景解析

2019阿里云峰会上海开发者大会于7月24日盛大开幕&#xff0c;本次峰会与未来世界的开发者们分享开源大数据、IT基础设施云化、数据库、云原生、物联网等领域的技术干货&#xff0c;共同探讨前沿科技趋势。本文整理自数据库专场中阿里云智能高级技术专家南仙的精彩演讲&#xff…

UML科普文,一篇文章掌握14种UML图

来源 | 如逆水行舟责编 | Carol封图 | CSDN 付费下载于视觉中国什么是UML&#xff1f;UML是Unified Model Language的缩写&#xff0c;中文是统一建模语言&#xff0c;是由一整套图表组成的标准化建模语言。为什么要用UML&#xff1f;通过使用UML使得在软件开发之前&#xff0c…

企业级数据库新型研发模式——数据管理DMS实践

2019阿里云峰会上海开发者大会于7月24日盛大开幕&#xff0c;本次峰会与未来世界的开发者们分享开源大数据、IT基础设施云化、数据库、云原生、物联网等领域的技术干货&#xff0c;共同探讨前沿科技趋势。本文整理自数据库专场中阿里云智能技术专家王天振 (为知)的精彩演讲&…

linux-centos7环境搭建

1、下载centos7 官网地址&#xff1a; http://isoredirect.centos.org/centos/7/isos/x86_64/ 阿里云&#xff1a; http://mirrors.aliyun.com/centos/ 以下针对各个版本的ISO镜像文件&#xff0c;进行一一说明&#xff1a; CentOS-7-x86_64-DVD-1708.iso 标准安装版&#x…

揭秘!机器人和你对话时在想什么?

阿里妹导读&#xff1a;为什么聊天机器人越来越普及&#xff1f;聊天机器人不仅可以节省时间&#xff0c;提升效率&#xff0c;还能一天24小时提供服务&#xff0c;更是可以减少误差。聊天机器人背后的问题原理是什么&#xff1f;效率如何提升&#xff1f;就是今天我们要了解的…

阿里云与A站在一起后,悄悄干了件大事

八月盛夏&#xff0c;“AcFun弹幕视频网站”&#xff08;简称“A站”&#xff09;的视频服务器全面迁移上阿里云&#xff08;此处应有掌声&#xff09;&#xff01; A站去年与阿里云达成此项合作。在迁移过程中&#xff0c;阿里云提供专业技术解决方案团队&#xff0c;为A站建立…

科大讯飞营收破百亿,员工涨薪27%,羡慕这个AI“老大哥”​了!

科大讯飞&#xff0c;中国AI公司“老大哥”&#xff0c;交出2019年成绩单。营收达到100.79亿&#xff0c;首次破百亿&#xff1b;净利润同比增长51.12%&#xff0c;达到8.19亿&#xff0c;日均盈利224万元&#xff0c;创下历史最佳业绩。与此同时&#xff0c;5大厂2020年应届生…

Knative Serving 之路由管理和 Ingress

Knative 默认会为每一个 Service 生成一个域名&#xff0c;并且 Istio Gateway 要根据域名判断当前的请求应该转发给哪个 Knative Service。Knative 默认使用的主域名是 example.com&#xff0c;这个域名是不能作为线上服务的。本文我首先介绍一下如何修改 默认主域名&#xff…

linux-centos7 关机命令、系统目录结构介绍

1、关机命令 关机指令 shutdown; sync # 将数据由内存同步到硬盘中&#xff0c;一般关机前需要同步一下&#xff0c;防止数据丢失shutdown # 关机指令&#xff0c;会在一定时间后关机&#xff0c;我试的是一分钟后关机shutdown -h 10 # 十分钟后关机 shutdown -h 10 # 十分…

SprinBoot2.X 集成 Flowable6.6 工作流引擎

上一篇&#xff1a;SpringBoot2.x Flowable 6.4.2 开源项目 码云开源地址&#xff1a;https://gitee.com/lwj/flow GitHub开源地址&#xff1a;https://github.com/ecnice/flow flowable学习 可以入群&#xff1a;633168411 说明:此项目是我师傅为了帮助更多小伙伴们入门工作流…

OceanBase高可用实践

背景 高可用是构建分布式系统的基石。一方面&#xff0c;出于成本考虑&#xff0c; 分布式系统往往采取比较廉价的硬件&#xff0c;其可靠性相对于小型机、专有硬件有很大的不足&#xff0c; 而分布式系统的规模一般比较大&#xff0c;假如硬件的可靠性只有三个9(99.9%)&#…

咦,拆分个字符串都这么讲究?

来源 | 沉默王二封图 | CSDN 付费下载于视觉中国提到拆分字符串&#xff0c;我猜你十有八九会撂下一句狠话&#xff0c;“这有什么难的&#xff0c;直接上 String 类的 split() 方法不就拉到了&#xff01;”假如你真的这么觉得&#xff0c;那可要注意了&#xff0c;事情远没这…

linux-centos7 常用的基本命令--目录管理、基本属性

一、目录管理 1、cd &#xff08;切换目录&#xff09; cd 路径 &#xff1a;切换路径命令&#xff0c;路径可以是绝对路径&#xff0c;也可以是相对路径 ./ : 当前目录 返回上级目录&#xff1a; cd … 返回用户目录&#xff1a; cd ~ 2、ls&#xff08;列出目录&#xff…

开源考试系统 - 本地代码调试运行

文章目录一、后端部署1. 图形化克隆项目2. 命令克隆项目3. 创建数据库&#xff0c;初始化数据库脚本4. IntelliJ IDEA打开项目5. 数据库连接和redis配置6. 启动redis和后端程序6. 浏览器访问二、前端部署2.1. 打开源码安装依赖2.2. 依次启动admin端和student端2.3. 浏览器访问补…

KDD 2019论文解读:异构信息网络上的对抗生成学习

前言 网络表示学习是一种在低维空间中表示网络数据的方法&#xff0c;在异构信息网络分析中得到了广泛的应用。现有的异构信息网络表示学习方法虽然在一定程度上实现了性能的提高&#xff0c;但仍然存在一些主要的不足。最重要的是&#xff0c;它们通常采用负抽样的方法从网络…

剖析疫情环境下的国内云市场:大势所趋,正是大展拳脚的好时机!

作者 | 马超责编 | Carol封图 | CSDN 付费下载于视觉中国4月29日&#xff0c;谷歌的母公司Alphabet正式发布了2020年第一季度财报&#xff0c;报告显示&#xff0c;Alphabet比去年同期的363.39亿美元增长13%&#xff0c;不计入汇率变动的影响为同比增长15%&#xff1b;在业绩公…

开源考试系统 -微信小程序开发

文章目录一、小程序前置准备1. 创建小程序2. 下载小程序开发工具二、小程序后端部署2.1. 配置修改2.2. 启动redis2.3. 启动后端项目三、小程序前端部署3.1. 微信小程序打开项目3.2. 学生端登录页面3.3. admin端登录一、小程序前置准备 1. 创建小程序 去腾讯小程序官网注册账号…

linux-centos7 常用的基本命令--文件内容查看、硬链接和软链接

一、文件内容查看 1、cat &#xff08;由第一行开始显示文件内容&#xff09; cat [-AbeEnstTuv] [--help] [--version] fileName参数说明&#xff1a; -n 或 --number&#xff1a;由 1 开始对所有输出的行数编号。-b 或 --number-nonblank&#xff1a;和 -n 相似&#xff0…