数据基础设施:数据处理语言概览

本文涉及的产品
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 为了让数据能够发挥其价值,需要对其进行一系列处理:查询检索、计算与转换、统计与分析。从使用者的角度来说,优秀数据处理引擎需要保证两个方面的优势:性能、易用性。在易用性方面一个趋势是从以前的传统的数据仓库可视化拖拖拽拽完成数据编排与处理,转变到现在云上数据平台更好的支持可编程方便开发者,可编程包括平台本身的API和数据处理过程的用户接口语言。在创造编程语言这件事情上,大家总是乐此不疲,在数据处理领域亦是如此,每个数据处理引擎出于特定场景易用性、生态集成等等原因,都会提供一种接口语言,统称为DSL(Domain Specific Language)。

简介

为了让数据能够发挥其价值,需要对其进行一系列处理:查询检索、计算与转换、统计与分析。

从使用者的角度来说,优秀数据处理引擎需要保证两个方面的优势:性能、易用性。在易用性方面一个趋势是从以前的传统的数据仓库可视化拖拖拽拽完成数据编排与处理,转变到现在云上数据平台更好的支持可编程方便开发者,可编程包括平台本身的API和数据处理过程的用户接口语言。在创造编程语言这件事情上,大家总是乐此不疲,在数据处理领域亦是如此,每个数据处理引擎出于特定场景易用性、生态集成等等原因,都会提供一种接口语言,统称为DSL(Domain Specific Language)。

数据处理语言的设计初衷是在某个场景下以极其简便的方式解决90%以上的最常见需求,主要原因是不同的数据场景面临不同的挑战和侧重点。接下来我们讨论一些就有代表性的数据处理语言。

数据处理语言

鼻祖Shell

Shell作为单机本地数据处理语言的开山鼻祖,其语法简洁易于理解,却异常强大。find | grep 轻松搞定数据的定位与检索,sedawk则作为文本数据处理和分析的利刃。来看个例子,从Nginx访问日志中统计IP的访问PV并降序排序,Shell命令如下:

awk'{print $1}' /var/logs/nginx/access.log | sort | uniq -c | sort-n-k1-r | more


Shell语法特比较有特色的设计是pipeline |,它使得Shell代码可以写的极其紧凑,而且逻辑清晰。这一点在很多后来的交互式数据查询分析语言中都会借鉴,比如Splunk SPL。

Shell作为人与Linux沟通的工具,数据处理只是他的一个应用场景,而且其处理能力也仅限于单机本地数据,所以很少会作为数据处理语言来讨论。

SQL称霸

SQL是Structured Query Language的缩写,设计之初是作为管理数据库的语言。目前来说,SQL语言无疑是数据处理领域的霸主,其一统数据处理的各个方向:事务型(OLTP)、分析型(OLAP,比如Presto、Spark SQL、Clickhouse)、流/批计算型(比如Spark Streaming、Flink SQL、Kafka KSQL)。

SQL的优点正如上所说,作为目前最通用的标准语言,其在任何一个数据引擎下几乎都可以做到脸熟,面向不同背景数据分析者,标准化也是一个相对普适的方案。对于新生的数据处理引擎来说,支持SQL就可以在一定程度上得益于这一点,运用其生态蕴含的能量。

不过标准SQL语言也是有局限的,文章《We Can Do Better Than SQL》已经做了完整的论述。在文章中,作者提出开源的EdgeQL,总体来说,这是一个混合了SQL和一般编程语言的数据处理DSL,这里不做赘述。

从数据处理角度来说,个人觉得SQL主要的局限有两点:

  1. 标准SQL很难实现过程计算,无法完成对数据的编排(比如多数据源汇集、多输出目标分发等场景),实现很多数据处理场景时需要异常复杂的逻辑嵌套,这也使得SQL的使用门槛比较高。有一篇博文介绍如何写出复杂数据处理场景的SQL语句《Complex SQL Query Example – Daily Order Analysis》,关于SQL的使用复杂性可以做个参考。
  2. 虽然在各个数据处理框架中都支持SQL,但为了实现特定的场景,一方面会在SQL标准上做扩展,另一方面会定义出丰富的内置场景计算函数,导致SQL代码没法直接跨平台迁移使用。所以平台化的SQL实质上就是一种DSL。

经典Splunk SPL

作为老牌日志大数据处理平台,他的成功其用户查询语言Search Processing Language (SPL)功不可没,极大的降低了数据分析的门槛。关于SPL的设计理念,在.conf2016的主题《Power of Splunk SPL》中作了详细的描述。个人觉得SPL最具特色的点:

  1. 将某些复杂却十分常用的场景通过特定指令完全封装,用户只需要简单的命令调用,就可以完成数据处理,几乎做到了极简。经典的命令比如stats、eventstats、streamstats、chart、timechart、transaction等。
  2. 场景化的查询命令可以与数据可视化无缝结合,搜索结果可以直接通过默认可视化展示,非常直观。

如下是从上述主题中截取的SPL基本结构图(通过一个查询语句说明):


最近一年Splunk也推出了新版语言SPL2,除了新增一些场景化的命令,最大的更新是增加了子序列概念,类似于建查询结果保存在视图中,后续的代码逻辑可以直接使用。也就是说一次查询可以写多条独立的逻辑,而不是完全依赖子查询,使得数据处理逻辑可以更加灵活。

// 定义子序列$prod_lookup
$prod_lookup =from sample_data_index 
where sourcetype LIKE"access_%"AND status=200| fields productId, product_name
// 使用子序列$prod_lookup
$prod_stats =from $prod_lookup
| stats count()by product_name

除了SPL,Splunk的操作界面、交互体验等也是很多后来者学习的案例。从产品角度来说Splunk确实是非常优秀,不过在后来“超大数据量”的发展时代中出现了很多更强大的竞争者,从性能、成本方面做到了超越。

云上平台Kusto Query Language (KQL)

Kusto是Azure Data Explorer的别名,面向的场景是大数据的准实时交互式(ad-hoc)查询分析平台。关于其产品细节,在《Azure Data Explorer(Kusto)学习笔记》一文中已有详细介绍,感兴趣请参考。

Kusto Query Language (KQL) 是Kusto提供的数据处理语言,其基本语法是 数据源 | 操作1 | 操作2。与Splunk SPL相比,其增加了多个数据源独立处理,相当于代码块。如下样例:

// 创建view
let Events = MyLogTable |where EventText like"ApplicationJobPerformance";// 过滤&关联
Logs 
|whereTimestamp> ago(1d)|join(  Events 
|where continent =='China')on RequestId


Kusto Query Language将配置管理(management or control commands)与数据处理两个场景需求融合到同一套语法中,这一点对于复杂数据编排场景非常友好。这一点有点类似于标准SQL中将DDL、DML、DCL融合在一起。比如,多目标数据分发场景下需要动态创建目标库,就可以通过同一个执行逻辑实现,而不需要其他API调用或者可视化操作。

// 创建表
.createtable Logs (Level:string,Text:string)// 将查询结果写入新的表
.set ErrLogs <| Logs |where Level =="Error"andTimestamp> now()-time(1h)

为了兼顾到熟悉SQL的人群,Kusto也支持SQL查询语法,命名为T-SQL。T-SQL并不是Kusto的最佳使用姿势,其使用场景存在很多限制,所以这里不做讨论。

老牌开源Elastic Stack

Elastic Stack是一个套装,包括数据存储Elasticsearch、可视化Kibana、以及采集组建Beats和Logstash,其常见的缩写比如ELK、EFK。在DB-Engines关于搜索引擎领域的排名中,Elasticsearch常年霸榜第一,评分遥遥领先排在其后的Splunk,足以说明其受欢迎的程度。

ELasticsearch提供了数据查询DSL作为用户操作数据的接口语言,其主要的场景是ad-hoc查询,其语法形式是通过JSON组织的抽象语法树。ELasticsearch DSL功能非常完善,可以实现全文检索、短语查询、正则匹配、统计分析等等场景,而且通过严格的JSON格式来保证语法无歧议。但是其JSON的语法形式的缺点是冗余高,使得DSL的用户使用体验并不理想。如下是一个DSL样例:

{
"query": {
"bool": {
"must": [
        {
"match": {
"position": "manager"          }
        },
        {
"range": {
"experience": {
"gte": 12            }
          }
        }
      ]
    }
  }
}


Kibana作为用户可视化操作数据的平台,为了优化上述ELasticsearch DSL使用体验不理想的问题,也提供了一种用户查询语言Kibana Query Language (KQL) ,用于数据的检索与过滤,没有实现统计与排序的能力。Kibana在请求ELasticsearch做查询之前,会将KQL翻译为ELasticsearch DSL。

如上繁琐的DSL可以转换为简洁的KQL:

position: manager and experience>=12


另外,Elastic Stack也提供了通过类似SQL的数据查询方案,通过X-Pack组件来实现的。同样的原理,其也是在运行时将SQL转换为DSL再做执行,也因此存在很多限制,其语法能力只支持部分SQL子集。

新兴Observe Processing and Analysis Language (OPAL)

Observe是一家的可观测性领域的创业公司,于2017年创建,前不久刚获得新增融资7000万美元。其目前的数据规模每天新导入数据40TB,执行2500万查询。其用户使用接口也设计了专门的数据处理语言Observe Processing and Analysis Language (OPAL),其形式设计同样是命令式,相较于上述Kusto语言,OPAL没有使用pipeline |作为命令连接。在面向复杂数据处理逻辑、需要连续的数十个命令场景中,这个设计相对于Kusto语言是更为简便的,减少了大量的|。接下来我们看下OPAL的一些创新设计。


一、数据过滤表达式。定义了很多数据匹配操作符,可以简化最常用的数据过滤场景,比如<...>作为文本搜索、~用于字段匹配、+表示多字段匹配等等。

// 短语匹配
filter <word1 word2>
filter <"words with spaces" or "special or">
// 字段匹配
filter content ~ <foo bar baz> // 等价 filter search(content, "foo", "bar", "baz")
filter message + error ~ <critical> // 等价 filter (message ~ <fatal>) or (error ~ <critical>)
// 正则匹配
filter match_regex(content, /foo|bar|baz/)


二、数据集Dataset与子查询Subquery(类似于代码块)定义。通过数据集的概念,直观的就可以完成多数据源操作。通过@符号指代默认数据集,简化最常用的单数据集场景。

// 子查询a,基于默认数据集产生临时数据集test_a

@test_a <- @ {
  filter city="上海"}
// 子查询b,基于数据集Weather产生临时数据集test_b
@test_b <- @Weather {
  filter city="上海"}
// 将两个临时数据集union,过滤并输出
<- @test_a {
  union @test_b
  filter contains(description, "cloud")
}


三、JSON作为“一等公民”,可以直接引用内部数据结构。最常见的数据结构使用简化。

// 直接引用
make_col userName:someField.user.name
make_col userCity:someField."user city"// 类似dict引用
make_col userName:someField.user.["name"]
make_col userCity:someField["user city"]


四、可以从原始数据中生成Metrics,支持指定label、不同指标类型(比如cumulativeCounter、gauge等)、不同的rollup计算(比如avg、count等)、还有多指标聚集(比如集群中每台机器都有CPU指标,我们需要的是集群的最高CPU)。

set_metric options(label:"Temperature", type:"gauge", unit:"C", rollup:"avg", aggregate:"avg", interval:5m), "temperature"set_metric options(label:"Power", description:"Power in watts", type:"gauge", rollup:"avg", aggregate:"avg"), "power"

总结

本文从数据处理语言角度来看数据基础设施,随着数据平台越来越成熟,数据处理语言也不停的推陈出新。

从语言设计来说,要通过一种语言完成所有场景是无法做到的,每一种数据处理引擎都会从起自身特点出发选择或者创建相应的数据处理语言。本文也只是列出了少部分具有代表性的数据处理语言,欢迎讨论。

参考链接

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。 &nbsp;
目录
相关文章
|
消息中间件 关系型数据库 Kafka
Flink CDC可以从Kafka消费数据并写入到Doris中
Flink CDC可以从Kafka消费数据并写入到Doris中
837 2
|
3月前
|
Web App开发 网络协议 应用服务中间件
HTTP2.0 从原理到实践,保证把你治得服服帖帖!
HTTP/2 是 HTTP/1.1 的重要升级,通过多路复用、头部压缩、服务器推送等特性显著提升性能与效率。本文详细解析了 HTTP/2 的优势、配置方法及实际应用,涵盖 Nginx/Apache/IIS 配置、curl 测试工具使用,并对比 HTTP/1.1 指出其优化点。同时提醒需注意 HTTPS 支持、客户端兼容性等问题,助你高效掌握并运用 HTTP/2 技术。
377 5
HTTP2.0 从原理到实践,保证把你治得服服帖帖!
|
5月前
|
算法 物联网 Swift
Qwen3 X ModelScope工具链: 飞速训练 + 全面评测
Qwen于近日发布了Qwen3系列模型,包含了各个不同规格的Dense模型和MoE模型。开源版本中,Dense模型基本沿用了之前的模型结构,差别之处在于对于Q和K两个tensor增加了RMSNorm;MoE模型去掉了公共Expert,其他结构基本与前一致。在模型大小上,涵盖了从0.6B到32B(Dense)和235B(MoE)不同的尺寸。
707 15
|
jenkins Java 关系型数据库
jenkins学习笔记之十二:sonarqube9.9、SonarScanner4.8部署
jenkins学习笔记之十二:sonarqube9.9、SonarScanner4.8部署
|
11月前
|
关系型数据库 MySQL Linux
Docker安装Mysql5.7,解决无法访问DockerHub问题
当 Docker Hub 无法访问时,可以通过配置国内镜像加速来解决应用安装失败和镜像拉取超时的问题。本文介绍了如何在 CentOS 上一键配置国内镜像加速,并成功拉取 MySQL 5.7 镜像。
1927 3
Docker安装Mysql5.7,解决无法访问DockerHub问题
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
400 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
资源调度 搜索推荐 Shell
使用VitePress静态网站生成器创建组件库文档网站并部署到GitHub
本文介绍了如何使用 Vue3、TypeScript 和 Vite 开发组件库并将其发布到 npm。文章详细描述了安装依赖、配置项目、创建文档网站以及编写组件文档的步骤。通过使用 VitePress,可以轻松搭建组件库的文档站点,并实现 Algolia 搜索功能。此外,还提供了自动化脚本用于部署静态网站至 GitHub 以及发布组件库到 npm。最后,展示了完整的目录结构和网站效果。
476 1
使用VitePress静态网站生成器创建组件库文档网站并部署到GitHub
|
10月前
|
SQL 关系型数据库 MySQL
|
安全 Unix Go
Golang深入浅出之-Go语言中的时间与日期处理:time包详解
【4月更文挑战第26天】Go语言的`time`包提供处理日期和时间的功能,包括`time.Time`类型、时间戳、格式化与解析。本文讨论了核心概念、常见问题(如时区处理、格式字符串混淆、超时控制和并发安全)及解决方法。推荐使用`time.LoadLocation`管理时区,熟悉时间格式规则,用`context`精确控制超时,并注意并发安全。文中通过代码示例展示了如何获取格式化时间、计算时间差以及创建定时任务。学习和应用这些知识可提高程序的健壮性和准确性。
586 2
|
Java
SpringBoot集成swagger后出现: Failed to start bean ‘documentationPluginsBootstrapper‘的解决方法
SpringBoot集成swagger后出现: Failed to start bean ‘documentationPluginsBootstrapper‘的解决方法
1110 0

热门文章

最新文章