没有索引也能用SQL ?深度解析 SLS Schema-on-Read 分析原理与应用

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: 为了能够更灵活的挖掘日志数据背后的价值,SLS提出了一种不需要事先建立索引就能对数据进行分析的模式。本文对SLS Schema-on-Read分析的提出背景、设计思路、实现过程、使用方式、适用场景进行了全面的介绍。

引言

日志数据的蓬勃发展

随着数字化浪潮下企业数字化转型进程的不断加速,以及云原生趋势下可观测性理念的逐渐普及,企业的日志数据的规模正在快速增长,同时日志数据的范畴也在不断扩大,包括但不限于:应用程序运行日志、Prometheus采集的云原生应用监控指标、服务器Syslog、网络访问日志、移动端监控数据、数据库binlog、业务埋点数据、账单数据、IoT设备上报数据等等。

这些数据有着丰富的用途,比如异常监测、故障诊断、安全风控、行为审计、运营报表、用户画像分析等等。为了能够发挥出数据背后的价值,企业不仅需要收集和存储海量的日志数据,同时更要能够对这些海量数据进行高效的计算和分析。


大数据技术的演进与SQL的回归

随着互联网的飞速发展,传统的关系型数据库逐渐难以满足海量数据的存储和查询需求,Google的“三驾马车”(MapReduce、GFS、BigTable)论文的发布,正式揭开了大数据时代的序幕。GFS 和 MapReduce 解决了数据大规模存储和计算的问题,只需要将大量普通的机器组织起来,就可以获得对海量数据的处理能力,从而大大降低了大数据技术的门槛。

这些新的数据技术的诞生,引发了一场传统数据库与大数据的论战,其中最出名的是数据库领域图灵奖得主Michael Stonebraker写的 MapReduce: A major step backwards ,批判MapReduce丢弃了传统数据库的理论精华,引用文章中的一段话:

数据库领域这四十年来中学到了三条重要的经验:

Schemas are good.

Separation of the schema from the application is good.

High-level access languages are good.

然而MapReduce没有吸收上面三个经验中的任何一个,甚至可以说是退步到了现代DBMS发明前的60年代。

尽管以今天的视角看这篇文章对于MapReduce的批判整体上有些稍显偏激了,但从上面这段话我们可以看出,基于关系模型的Schema定义、声明式的SQL语言对于数据库的发展是至关重要的,在这个基础上,计算的“逻辑意图表达”与计算的“物理执行过程”被解耦开来,使用者只需要使用SQL去表达自己“需要算什么”,至于“怎么去算“则完全交给数据库执行引擎自己去优化,这种解耦大大降低了数据库的使用难度,从而极大地促进了数据库的普及。


这场论战最终的结果是大数据技术与传统数据库技术都发现了对方的优点,双方取长补短、相互融合。正如Google自己在后续发布的Spanner论文(Spanner: Becoming a SQL System)中这样说到:

虽然这些系统提供了数据库系统的一些优点,但它们缺乏应用程序开发人员经常依赖的许多传统数据库特性。一个关键的例子是健壮的查询语言,这意味着开发人员必须编写复杂的代码来处理和聚合应用程序中的数据。因此,我们决定把Spanner变成一个功能齐全的SQL系统,查询执行与Spanner的其他架构特性紧密结合。

大数据领域这边吸收了传统数据库中的索引优化、查询优化、SQL语言等技术,演进出了各种SQL-on-Hadoop的解决方案,如Hive、Spark SQL、Presto等,如今对于SQL的支持基本已经成为各种大数据计算引擎的标配。而数据库领域则向着分布式、HTAP等方向演进着。

这些融合标志着SQL重新回归,成为数据分析处理系统的通用接口。


关系模型的约束与Schema-on-Read的兴起

SQL之所以能够具备强大的计算表达能力和优越的执行友好性,是建立在对数据模型的严格要求上。

SQL背后的理论基础是关系代数,关系模型则要求数据预先定义好Schema(有哪些表,每张表有哪些列,每一列的类型是什么),然后按照定义好的Schema去写数据。相对应的,文档模型则对于数据Schema的要求非常灵活,每条数据就是一个文档,文档内部的数据格式不做严格限定。

正所谓天下没有免费的午餐,这种对数据模型的限制,反过来也会成为一种对灵活性的束缚。在大数据场景中,半结构化、无结构化的数据是非常常见的,因此也催生了 Schema-on-Write 和 Schema-on-Read 两种不同的处理方式

image.png


Schema-on-Write指的是数据的Schema是预先定义好的,数据在写入数据仓库之前,必须要按照定义好的Schema去写入,如果原始数据不符合定义的Schema,则需要先通过一些ETL的过程去对数据进行清洗加工,然后再写入。数据写入的同时,一般也同时会根据确定的Schema建立一些索引结构,查询的时候也同样直接按照确定的Schema去查询,往往能够获得较好的查询性能。


而Schema-on-Read指的是原始数据在写入的时候不做过多的校验,而是在读取的时候“动态”的决定以何种视角去看待数据,类似在数据之上按需建立一个视图,这种方式显然更灵活,但相应的性能上会一般会打一些折扣。


日志分析场景下的SQL

日志数据天然是弱Schema的

image.png

从数据模型的角度看,日志数据天然难以具备规范的Schema:

  • 来源多样性:日志数据种类繁多,不同来源的数据难以具有统一的Schema
  • 数据随机性:比如异常事件日志、用户行为日志,往往天然就是随机的,难以预测的
  • 业务复杂度:不同的参与方对schema的理解不同,比如开发流程中打日志的往往是开发者,但分析日志的往往是运维和运营,写日志过程中没有足够预见性导致不能被分析人员直接使用


对于SLS这样的日志平台来说,SLS的日志数据可以从各种数据源采集过来,写入的时候可以灵活的格式写入,因此可以看做是文档模型,每条日志就是一个文档。而SQL要求是数据必须遵从关系模型,因此从数据模型的角度这其中就必然存在一个Gap,导致难以直接在原始数据上使用SQL进行查询。


基于索引和列存的Schema-on-Write SQL

在数据系统中,由于处理场景的多样性,往往单一的数据形式是无法满足所有的需求,因此就有了记录数据和派生数据的概念。

  • 记录数据(record data):指的是原始数据,只会在系统中存一份
  • 派生数据(derived data):指的是从原始数据衍生出的各种形式的数据,如索引、缓存、物化视图等等。派生数据是原始数据的冗余,本质上都是为了不同的读取场景进行优化。

对于日志场景,SLS也是同样的做法,原始数据采集上来后,会生成出索引、列存、metric等不同形式的派生数据,分别用于搜索、SQL和时序场景。

image.png

对于SLS的SQL来说,主要是依赖列存。SLS的原始数据可以是半结构或者无结构化的,而派生出的列存数据是结构化的,严格遵从关系数据模型,这样就解决了SQL对于数据模型的要求。此外,对于分析场景,列存在压缩比例、cache友好性、IO效率上相比于行存有着极大的优势,再配合索引的快速filter能力,极大的提高了SQL分析的性能。

从Schema的角度看,虽然SLS原始数据写入没有Schema要求,但是列存是必须先定义Schema,然后写入的时候按照Schema写入(SLS构建列存时进行的转换),查询分析的时候也按照定义好的Schema进行分析。

因此从SQL的视角看,这是一个标准的Schema-on-Write的模式。


用户增效降本的诉求

基于索引和列存的SQL的模式,可以很好的支持绝大部分的SQL分析需求。然而对于弱Schema和写多读少的场景,用户往往会有增效降本的诉求,具体表现在:

增效——固定Schema的限制

前面说到日志数据天然是弱Schema的,意味着Schema的不确定是常态。

  • 当Schema发生变化时,必须要去更新索引,频繁索引操作带来运维负担
  • 非结构化的日志数据,可能字段数目非常多,无法一一枚举,或者会有新增字段难以提前预测,这些情况下难以去创建对应的字段索引
  • 如果字段发生变化未及时感知到,对于索引变更前的历史数据,需要重建索引,重建索引带来索引流量费用,且超过30天的历史数据无法重建
  • 构建列存时的字段长度是有限制的(默认2k,最大支持16k),如果字段过长,超出的部分会被截断无法分析

降本——派生数据带来的成本

现有模式下,为了满足关系模型和保证查询的高性能,必须要构建索引和列存,从而产生索引流量和索引存储的成本。

  • 写多读少的场景,比如异常排查、审计,往往只在很少的时候需要分析,但是也必须全部开启索引
  • 非结构化数据中的长尾字段,即使数据价值密度很低,但是为了潜在的分析需求,也不得不提前开启索引

这些场景下,全量字段开启索引所产生的费用可能与实际产生的数据价值并不匹配,但不开启索引又完全无法在需要的时候进行分析。

因此如果要增效降本,则增效意味着要突破固定Schema的限制,降本意味着不要去依赖额外的派生数据。那么我们能否基于Schema-on-Read的理念,在原始数据上动态的应用Schema去完成分析需求呢?


SLS Schema-on-Read SQL设计与实现

需要解决的问题

我们来重新审视下基于索引和列存的Schema-on-Write模式的SQL实现,这里面索引和列存实际上提供了两个作用:

  • 创建字段索引的时候,指定了有哪些字段,每个字段是什么类型,相当于创建了一个关系模型的Schema
  • 字段索引开启统计后,会为字段构建列存,从而在执行时可以高效读取指定列的数据

相对应的,如果要实现Schema-on-Read,从技术实现角度至少需要解决以下两个问题:

(1)没有Schema信息,SQL引擎怎么执行?

SQL执行引擎都是遵从关系数据模型,一般都是遵从强Schema设计的,因此需要知道每张表有哪些列,每一列是什么类型。如果没有这些信息,SQL引擎将无法执行下去。

(2)没有列存数据,怎么读取指定列的数据?

只有原始的非结构化的行存数据,没有列存这种结构化的数据。需要从这种非结构化的行存数据中,提取出SQL分析需要的列的数据。


关键点一:从SQL语句中自动推断schema

首先针对第一个问题,没有Schema信息,SQL引擎如何执行?

其实很多Schema-on-Read的实现是这样做的:写入的时候是直接写入存储,这一步不会对数据类型做太强的限制(比如HDFS或者对象存储),读取的时候需要先通过类似Create Table语句定义一个表(定义数据源、要分析的列的类型等等),然后基于这个表进行查询。不同的查询需求可以定义不同的表,这个也是符合Schema-on-Read的理念的。

然而日志场景下我们对Schema这个问题有着进一步的思考:

  • 日志分析场景是非常强调交互式分析的灵活性的,试想一下,如果在每执行一条SQL语句对日志进行之前,都要先执行Create Table创建一个表,那么使用起来将会非常的不便捷
  • 在SLS的查询分析时,是指定了project和logstore信息的,也就是数据源的存储相关元信息已经知道了,唯一缺的只是列的信息(要分析哪些列,每个列是什么类型)
  • 而要分析哪些列,这个信息实际上是可以从SQL语句本身推断出来的,类型可以默认都为varchar(其他类型需要用cast语句转换下)

因此我们的做法是:从用户输入的SQL语句中自动推断出所需要的Schema。

这里举一个最简单的SQL语句的例子,Select id,login from users,这条SQL语句经过词法分析和语法分析后,会对原始语句进行分词并构建出一棵抽象语法树,语法树里面就隐含了这条语句需要什么样的Schema,比如对于刚才这条SQL语句,我们就可以从语法树中推断出,需要从users表里面,读取id和login这两列,类型分别是varchar,这就是这条语句所需要的schema信息。

image.png

实际情况下这个推断过程需要考虑更多复杂的场景,比如多个表join、多级sql嵌套、表别名等等,但是基本原理上和上面这个例子是相同的,从语法树中提取出Table节点,以及与这个Table节点相关联的Identifier节点,然后组成对应的Schema信息。


关键点二:从原始数据中自动构建列式数据

第二个要解决的问题是在执行数据读取的过程中,如何从非结构化的原始数据中,匹配提取出结构化的数据来参与计算。

这个过程在原理上是比较直观的,就是扫描原始数据,匹配提取出要读取的字段。在实现层面主要是要尽可能的提升这个扫描匹配过程的效率。

举个例子,比如 select count(1) as pv, Api, Status group by Api, Status 这条SQL语句,前面在Schema推断的过程中,会推断出有一张临时表,表里面包含了Api、Status这两列的数据。在执行阶段,就需要从原始数据中,读取出只属于这两列的数据。

image.png

后续的提取列式数据的过程是这样的:

  • 通过时间范围和索引查询条件,过滤出需要扫描的原始数据
  • 对分析的列名称求hash
  • 对待扫描的原始数据进行逐行逐字段扫描,计算字段hash并和待分析的列的hash进行比较,匹配上则提取出对应的字段值,未匹配上则填充null
  • 计算过程中优先比较上次匹配位置、记录已匹配情况提前终止等方式尽量减少循环次数
  • 此外,结合LRU缓存、亲和性调度等优化,尽可能减少重复扫描

经过上述这些优化,可以有效的提高整个匹配过程的效率。

以上就是SLS Schema-on-Read设计中两个关键问题的实现思路。


SLS 扫描分析模式介绍

扫描模式——SLS Schema-on-Read 查询/分析 解决方案

SLS的Schema-on-Read查询分析方案,在产品功能上称为“扫描模式”(也称为“Scan模式”),以区别于Schema-on-Write的索引模式。

扫描模式,顾名思义,不依赖于事先开启索引和列存,而是通过直接对原始数据进行“硬扫描”来进行相应的计算。

扫描模式和索引模式等不同的计算模式,以及查询型、分析型、冷热存储等不同存储选型,共同组合成SLS计算存储引擎面向不同场景下多样化的解决方案。

image.png


扫描查询与扫描分析的关系

和索引模式相同,扫描模式也分为扫描查询和扫描分析,扫描查询先前已经发布,具体可以参考《聊聊日志硬扫描,阿里 Log Scan 的设计与实践》这篇文章。

在介绍新推出的扫描分析能力之前,先看下扫描查询和扫描分析的联系和区别:

  • 语法上竖线前都是索引字段过滤,竖线后是对原始数据硬扫描,并按照实际扫描的数据量计费
  • 扫描查询竖线后是“where + 布尔表达式”,用来条件过滤;扫描分析竖线后是标准SQL,用来进行聚合、关联分析
  • 扫描查询是检索原文,可以不断的往后翻页;扫描分析一般是用来算聚合指标,是对范围内数据的一次性分析。

image.png


扫描分析使用方式

控制台开启扫描模式

在控制台的“查询分析”右侧有一个“Scan扫描”的模式开关,打开这个开关表明开启 schema-on-read 能力(无需预先构建索引)

打开这个扫描模式的开关后,在控制台直接写分析语句即可:

  • 扫描分析模式下,分析语句是标准SQL,和索引模式下完全相同
  • 扫描分析模式下,SQL语句里待分析的字段(如下图中的UserAgent字段)无须事先建立索引

image.png

执行完扫描分析语句后,在柱状图的下方,可以看到一栏统计信息

  • “分析模式:Scan模式”,这个表明当前工作在扫描模式下
  • “扫描数据量”表示在执行这次SQL的过程中,实际扫描的原始数据量,将会按照这个数据量计费。

注意扫描流量是针对在查询条件过滤之后的数据计算。以上面这个截图中的例子,比如最近4小时是有1亿条数据,经过查询条件“Method:Head and Status:500”(Method字段和Status字段开启了索引)过滤后有600万条,则扫描过程是针对这600万条数据进行的,扫描数据量是统计的实际扫描的数据量大小。

通过Session参数开启扫描模式

更通用的开启扫描模式的做法是,在分析语句上设置Session参数set session mode=scan,比如 “* | set session mode=scan; select api, count(1) as pv group by api

值得一提的是,对于SDK调用、告警、仪表盘、定时SQL等所有可以写sql语句的地方,都可以通过添加这个session参数来开启扫描模式。


没有银弹——扫描模式分析能力是有限的

在数据分析中,性能、成本、灵活性是一组“不可能三角”,Schema-on-Read分析模式增加了灵活性,降低了成本,则必然要付出性能上的牺牲。

image.png

影响扫描分析模式的性能的因素具体体现在:

  • 读原始数据的IO放大

索引模式下只需要从磁盘单独读取指定列的列存数据,而扫描模式下需要读取所有的原始数据,此外列存数据的压缩比也远远优于原始行存数据。这个是影响性能的主要部分。具体则取决于扫描行数、单条日志数据量大小、被扫描的数据分布(是连续的数据,还是通过索引条件过滤后的稀疏数据)等因素。

  • 额外的扫描时间

扫描模式下还需要对读取的原始数据进行遍历,匹配提取待分析的字段,这个过程也需要消耗一定的计算时间。


为了保证最终的执行时间在一个可接受的范围内,目前扫描分析模式下会对扫描行数进行限制(单次sql,限制单个shard扫描50w行,总扫描行数1000w行),超出这个限制会返回不精确的部分计算结果。


SLS 扫描分析模式典型使用场景

情形一:Schema不确定的场景

扫描模式最重要的场景就是应对Schema无法事先确定(从而无法事先创建好对应的字段索引)的情况,这在日志场景中是非常常见的,比如:

  • 同一个logstore采集多个服务的日志,不同的采集配置对应的字段不完全相同
  • 日志文件本身是自描述的,比如通过logtail采集JSON格式日志,或者通过OSS导入CSV格式文件,这些格式下字段都是可变的
  • 通过sdk写入日志,根据运行时情况动态写入不同的日志字段
  • 通过数据加工或者定时SQL写入的日志数据,加工程序进行了修改导致字段发生变化
  • 等等

在固定Schema的索引模式下,对于这类情况比较难解决:

  • 要么就是发生变化后去修改索引(问题:运维成本太高,而且可能字段太多无法都创建索引)
  • 要么只能通过一定的约束保证产生的日志字段都相同(问题:可能无法做到)
  • 要么通过数据加工进行二次加工清洗(问题:数据链路变长,额外的加工和存储成本)
  • 或者甚至干脆用一个字段去存储所有数据,然后用sql里的json函数或者正则函数去提取需要分析的字段(问题:日志不便于阅读、单条长度可能超过字段索引长度限制、sql书写复杂、sql执行时每一条都要执行提取函数性能差)

有了扫描模式之后,可以只对高频出现的固定字段建立索引(如果不考虑成本因素也可以直接建立全文索引),对于长尾的可变字段不需要建立字段索引,从而不需要疲于应对schema的不断变化。


一个JSON格式日志的例子

举个开发同学比较熟悉的例子,比如go语言中常用的Zap Logger,输出到日志文件中是打印成json形式,程序中可以通过zap.XXX添加json日志中的一个字段。

比如A同学通过这行代码,记录访问db的延时情况:

logger.Info(
  "request-db",
  zap.Int("latency", latency),
  zap.String("url", url))

打印出的日志是下面这样的json格式(略去时间戳、日志级别等公共字段),通过JSON模式采集到sls之后,在logstore就会新出现了status、url等新增字段,索引模式下为了能够分析这两个字段,需要给这两个字段增加索引。

{
    "msg":"request-db",
    "latency": 103,
    "url": "mock.host"
}


接下来B同学在增加了这样的日志,来记录某个临时增加的活动里发放的优惠券的类型和金额信息,这里面又新增了两个字段,有需要新增索引

logger.Info(
  "discount",
  zap.Int("type", discountType),
  zap.String("amount", amount))

由于每个开发同学都可能会在代码中根据当前上下文打印自己需要的字段,其结果是最终日志文件中的可能的字段非常多,无法一一建立索引进行分析。为了解决这个问题,往往不得不要求开发同学将所有信息都打在公共的msg字段里,再只对msg字段建立索引并开启统计。然而这样实际上丢失了json格式的优势,分析的时候也非常不方便。

而在有了扫描分析模式之后,对于上面这种json日志格式,可以只对固定的msg字段开启索引,其他可变字段无须开启索引。

image.png

现在比如A同学要分析“访问不同的db的平均延时的分布”,就可以这样直接通过扫描模式进行sql分析:

msg:request-db | set session mode=scan; select avg(cast(latency as bigint)) as avgLatency, url group by url order by avgLatency desc

注意:扫描分析模式下字段被视为varchar,因此对这里的latency要转为数字类型才能求均值

而B同学要去分析“不同类型的优惠券分别发放了多少金额”,则可以这样进行分析:

msg:discount-coupon | set session mode=scan; select sum(cast(amount as bigint)) as totalAmount, type group by type order by totalAmount desc

这样打印日志的时候,就可以针对特定场景自由的新增自己关心的特征日志用于分析,而不需要考虑索引的变更。

在分析的时候,先用相应的关键词过滤下(过滤后保证日志都是符合要分析的结构的,而且降低了扫描规模),然后再使用扫描分析模式,就可以直接通过sql分析自定义的指标字段。


情形二:写多读少的降本场景

对于写多读少的场景,如果日志的业务方经过分析,认为有部分字段不需要高频的查询分析,没有必要对100%的日志开启索引,希望合理降低日志的成本。

这里举个参考的例子,做如下假设:

  • 每条日志大小是1KB,有10个字段,分别是 key_0/key_1/.../key_9,其中 key_0/key_1 是被经常会被查询分析,其余8个字段很少使用。
  • 每天日志量10亿条(即1TB),存储周期7天,日志压缩率按6计算
  • 对key_2/.../key_9这8个低频字段的分析频次是每天200次,每次分析时需要扫描500万条日志(即5GB)

按照现有中国站列表价简单估算如下:

100%索引 方案

20%索引 + 扫描 方案

写入流量(压缩后)

0.17 TB/天

0.17 TB/天

索引流量

1TB/天

0.2 TB/天

索引存储量

7TB

1.4 TB

原文存储量(压缩后)

1.17 TB

1.17 TB

扫描流量

0

1 TB/天

单日费用

¥486

¥183

按照上述例子的假设,使用扫描模式可以有效降低使用成本。不过实际评估的时候还需要注意:

  • 扫描模式能够分析的数据量有限,耗时也会上升,需要评估业务上能否接受
  • 扫描分析模式下评估成本的关键因素是扫描流量。上述例子中每天1TB的扫描流量的费用是51.2元,对于不同的分析qps、单次扫描数日志行数、单条日志大小,最后算出来的扫描流量费用的差别会很大,需要根据实际业务情况评估。如果需要分析的频次比较高并扫描的数据量大,建议还是使用索引模式。


情形三:无法使用索引分析模式的场景

由于扫描分析模式只依赖原始数据,不依赖索引或者列存等任何派生数据,因此对于下面这些无法使用索引模式的场景,可以使用扫描模式进行分析。

查询型Logstore/Lite版本

查询型Logstore(也称为Lite版本)的定位是支持需要低成本长期存储、只需要查询不需要分析的场景,索引流量费用更低,但不支持SQL分析(无法为索引字段勾选“开启统计”)。

新推出的扫描分析模式也可以在查询型Logstore上进行使用,从而具备一定的分析能力。


无索引的历史数据

某些情况下可能想分析的字段没有索引,比如:

  • 创建Logstore后没有及时开启索引配置,但是数据已经写入了
  • Schema发生变化后没有及时更新索引配置,因此新增的字段就没有索引

目前SLS有对历史数据重建索引的功能,但是只能重建30天内的数据。对于超过30天的历史数据,之前的解法是使用数据加工写到一个新的创建好索引的logstore中,这种做法可以彻底解决问题,但会增加额外的成本。

现在有了扫描模式之后,如果历史数据需要分析的数据规模不大(或者可以通过已有的索引字段进行辅助过滤),则可以使用扫描模式对历史数据直接进行分析。


日志字段超出索引长度限制

索引分析模式下,字段能够被分析最大长度有限制(默认2k,可以调整配置,最大调整到16k),背后的原因是因为构建列存的时候,对列存的单条记录的长度有限制。超出长度的部分被截断,无法参与分析。

在扫描分析模式下,因为是直接对原始数据进行扫描的,对于这种字段长度超出限制的场景,可以使用扫描分析模式进行分析。

不过需要注意的是,无论是从分析性能还是灵活性上考虑,日志采集的最佳实践仍然是尽可能的按照日志结构对字段进行拆分,而不是都放在一个字段里。正如前面JSON日志的例子中指出的,可以对固定的、需要高频分析的字段建立索引并开启统计,对低频的、可变的字段使用扫描模式。


总结与展望

本文首先简要回顾了大数据技术的发展历程中,SQL逐渐成为数据分析领域的通用语言,而由于关系模型对Schema的约束,催生了Schema-on-Read概念的兴起。

日志数据天然是弱Schema的,为了能够支持SQL,现有的做法是先定义好Schema,从原始非结构化数据中冗余一份结构化的符合关系模型的数据(列存),但这样又带来了灵活性不够和成本上升的问题。

为了满足增效降本的诉求,SLS基于Schma-on-Read的理念,推出了扫描分析模式,无须在查询前先声明Schema,直接书写SQL语句即可在原始的非结构化数据上进行计算分析,在Schema多变的场景下能够体现出极大的灵活性,同时也能用于写多读少场景下的降本。

同时也正如文中数次提到的,扫描模式不是银弹,并不能取代索引模式。在分析的数据规模大、分析频次高、分析性能有要求的场景下仍然需要首选索引模式,扫描模式则主要面向中小数据规模、Schema不确定、写多读少以及一些无法使用索引分析的场景。


扫描查询/分析模式是SLS在Schema-on-Read分析场景的探索,未来将继续结合存储模式的演进、计算性能的提升,进一步大幅增强Schema-on-Read计算分析模式的性能和灵活性。

目前扫描分析模式已经在各个地域陆续发布上线,欢迎参考官方文档进行体验使用。

参考

1、Demystifying Data Explorer:https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/demystifying-data-explorer/ba-p/3636191

2、MapReduce: A major step backwards:https://homes.cs.washington.edu/~billhowe/mapreduce_a_major_step_backwards.html

3、Designing Data Intensive Applications:https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/

4、Why SQL is beating NoSQL and what this means for the future of data:https://www.timescale.com/blog/why-sql-beating-nosql-what-this-means-for-future-of-data-time-series-database-348b777b847a/

5、Spanner: Becoming a SQL System:https://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/46103.pdf

6、大数据技术发展简史:https://cloud.tencent.com/developer/article/1640405

7、扫描分析模式概述:https://help.aliyun.com/document_detail/473045.html

8、标准型与查询型Logstore介绍:https://help.aliyun.com/document_detail/48990.html

目录
相关文章
|
20天前
|
数据库 索引
深入探索数据库索引技术:回表与索引下推解析
【10月更文挑战第15天】在数据库查询优化的领域中,回表和索引下推是两个核心概念,它们对于提高查询性能至关重要。本文将详细解释这两个术语,并探讨它们在数据库操作中的作用和影响。
43 3
|
11天前
|
存储 SQL 监控
|
11天前
|
运维 监控 安全
|
14天前
|
监控 关系型数据库 MySQL
分析慢查询日志
【10月更文挑战第29天】分析慢查询日志
35 3
|
14天前
|
监控 关系型数据库 数据库
怎样分析慢查询日志?
【10月更文挑战第29天】怎样分析慢查询日志?
32 2
|
1月前
|
SQL Oracle 关系型数据库
SQL优化-使用联合索引和函数索引
在一次例行巡检中,发现一条使用 `to_char` 函数将日期转换为字符串的 SQL 语句 CPU 利用率很高。为了优化该语句,首先分析了 where 条件中各列的选择性,并创建了不同类型的索引,包括普通索引、函数索引和虚拟列索引。通过对比不同索引的执行计划,最终确定了使用复合索引(包含函数表达式)能够显著降低查询成本,提高执行效率。
|
8天前
|
SQL 监控 安全
员工上网行为监控软件:SQL 在数据查询监控中的应用解析
在数字化办公环境中,员工上网行为监控软件对企业网络安全和管理至关重要。通过 SQL 查询和分析数据库中的数据,企业可以精准了解员工的上网行为,包括基础查询、复杂条件查询、数据统计与分析等,从而提高网络管理和安全防护的效率。
20 0
|
30天前
|
SQL 监控 数据库
SQL语句是否都需要解析及其相关技巧和方法
在数据库管理中,SQL(结构化查询语言)语句的使用无处不在,它们负责数据的查询、插入、更新和删除等操作
|
30天前
|
SQL 数据可视化 BI
SQL语句及查询结果解析:技巧与方法
在数据库管理和数据分析中,SQL语句扮演着至关重要的角色
|
1月前
|
SQL 监控 关系型数据库
SQL错误代码1303解析与处理方法
在SQL编程和数据库管理中,遇到错误代码是常有的事,其中错误代码1303在不同数据库系统中可能代表不同的含义

推荐镜像

更多