简介
为了让数据能够发挥其价值,需要对其进行一系列处理:查询检索、计算与转换、统计与分析。
从使用者的角度来说,优秀数据处理引擎需要保证两个方面的优势:性能、易用性。在易用性方面一个趋势是从以前的传统的数据仓库可视化拖拖拽拽完成数据编排与处理,转变到现在云上数据平台更好的支持可编程方便开发者,可编程包括平台本身的API和数据处理过程的用户接口语言。在创造编程语言这件事情上,大家总是乐此不疲,在数据处理领域亦是如此,每个数据处理引擎出于特定场景易用性、生态集成等等原因,都会提供一种接口语言,统称为DSL(Domain Specific Language)。
数据处理语言的设计初衷是在某个场景下以极其简便的方式解决90%以上的最常见需求,主要原因是不同的数据场景面临不同的挑战和侧重点。接下来我们讨论一些就有代表性的数据处理语言。
数据处理语言
鼻祖Shell
Shell作为单机本地数据处理语言的开山鼻祖,其语法简洁易于理解,却异常强大。find | grep
轻松搞定数据的定位与检索,sed
和awk
则作为文本数据处理和分析的利刃。来看个例子,从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主要的局限有两点:
- 标准SQL很难实现过程计算,无法完成对数据的编排(比如多数据源汇集、多输出目标分发等场景),实现很多数据处理场景时需要异常复杂的逻辑嵌套,这也使得SQL的使用门槛比较高。有一篇博文介绍如何写出复杂数据处理场景的SQL语句《Complex SQL Query Example – Daily Order Analysis》,关于SQL的使用复杂性可以做个参考。
- 虽然在各个数据处理框架中都支持SQL,但为了实现特定的场景,一方面会在SQL标准上做扩展,另一方面会定义出丰富的内置场景计算函数,导致SQL代码没法直接跨平台迁移使用。所以平台化的SQL实质上就是一种DSL。
经典Splunk SPL
作为老牌日志大数据处理平台,他的成功其用户查询语言Search Processing Language (SPL)功不可没,极大的降低了数据分析的门槛。关于SPL的设计理念,在.conf2016的主题《Power of Splunk SPL》中作了详细的描述。个人觉得SPL最具特色的点:
- 将某些复杂却十分常用的场景通过特定指令完全封装,用户只需要简单的命令调用,就可以完成数据处理,几乎做到了极简。经典的命令比如stats、eventstats、streamstats、chart、timechart、transaction等。
- 场景化的查询命令可以与数据可视化无缝结合,搜索结果可以直接通过默认可视化展示,非常直观。
如下是从上述主题中截取的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"
总结
本文从数据处理语言角度来看数据基础设施,随着数据平台越来越成熟,数据处理语言也不停的推陈出新。
从语言设计来说,要通过一种语言完成所有场景是无法做到的,每一种数据处理引擎都会从起自身特点出发选择或者创建相应的数据处理语言。本文也只是列出了少部分具有代表性的数据处理语言,欢迎讨论。
参考链接
- Linux Shell Commands https://docs.cs.cf.ac.uk/notes/linux-shell-commands/
- SQL标准演变史 https://learnsql.com/blog/history-of-sql-standards/
- 《We Can Do Better Than SQL》 https://www.edgedb.com/blog/we-can-do-better-than-sql
- 《Complex SQL Query Example – Daily Order Analysis》https://www.databasestar.com/complex-sql-query-example/
- 《Power of Splunk SPL》https://conf.splunk.com/files/2016/slides/power-of-spl.pdf
- 《Azure Data Explorer(Kusto)学习笔记》https://developer.aliyun.com/article/701041
- Elasticsearch Query DSL文档 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
- Kibana Query Language文档 https://www.elastic.co/guide/en/kibana/master/kuery-query.html
- Observe Processing and Analysis Language (OPAL) 官方文档 https://docs.observeinc.com/en/latest/content/query-language-reference/ObserveProcessingAndAnalysisLanguage.html