数据库查询语言的进化(中)

一 | 用进化的视角看数据库和查询语言的演进

在过去的半个世纪,数据库技术及查询语言的进化历程简而概之:

·70年代之前:导航型数据库;

·70—80年代:关系型数据库;

·90年代:SQL编程语言兴起;

·21世纪第一个10年后:出现各种NoSQL(NoSQL=NotOnly SQL,不仅仅是SQL!)

进化的视角看数据库和查询语言的进化历史

如果读者对于SQL语言的演进有所了解的话,就知道是它直接推动了关系型数据库的发展。此外,互联网的崛起还催生了NoSQL的诞生和崛起,其中很大的一个因素是关系型数据库无法很好的应对数据处理速度、数据建模灵活性的诉求。

NoSQL数据库一般被分为以下5类,每一类都有其各自的特性:

·键值: 性能和简易性

·宽列:体量与性能

·文档:数据多样性

· 图: 深数据+快数据

· (可选的)时序:IOT数据、时序优先性能

在这里插入图片描述

上图中,SQL被认为是最先进的数据处理与查询语言。我们需要稍微深入的研究一下SQL的演化历史,来帮助我们有个更全局化的观念。

SQL的出现已经将近50年了,并且已经迭代了很多版本(平均每3-4年一次大迭代),其中最知名的非SQL-92、99莫属,例如在92版本中在FROM语句中增加了子查询(subquery)功能;在99 年版本中增加了CTE (Common Table Expression)功能。这些功能极大的增加了关系型数据库的灵活性(如下图所示)。

Subquery per SQL-92 and CTE per SQL-99
然后,关系型数据库始终存在一个“弱点”,那就是对于递归型数据结构的支持(Recursive data structures)。所谓递归数据结构,指的是有向关系图的功能实现。令人感到讽刺的是,关系型数据库的名字虽然包含了关系,但是它在设计伊始就很难支持关联关系的查询。为了实现关联查询,关系型数据库不得不依赖表连接操作 — 每一次表连接都意味着潜在的表扫描操作,以及随之而来的性能的指数级下降,以及SQL语句、代码的复杂度的直线上升!

表连接操作的性能损耗是直接源自于关系型数据库的基础设计思想的:

· 数据正则化(Data Normalization)
· 固定化的、预先设定的表模式(Fixed/Predefined Schema)

如果我们看一下NoSQL中的核心理念,在数据建模中突出了数据去正则化。所谓数据正则化,指的是用空间换取时间(牺牲空间来换取更高的性能!),在NoSQL(也包括Hadoop等,例如典型的3、5、7份拷贝的理念)中,数据经常被以多份拷贝的方式存储 ,而这样做的好处在于数据可以以紧邻计算资源的方式被处理。这种理念和SQL中的只存一份正则化设计思路是截然相反的 – 后者或许可以节省一些存储空间,但是对于复杂的SQL操作而言,带来的是性能的损耗。

预先定义数据的表模式的理念是SQL与NoSQL的另一大差异。对于初次接触这一概念的读者而言,理解这个点会有些复杂,从下面这个角度去理解或许更直观:
在这里插入图片描述
在关系型数据库中,系统管理员(DBA),需要先定义表的结构(schema),然后才会加载第一行数据进入数据库,他不可能动态的更改表的结构。这种僵化性对于固定模式、一成不变的数据结构和业务需求而言或许不是什么大问题。但是,让我们想象一下如果数据模式可以自我调整,并能根据流入的数据动态调整,这就给了我们极大的灵活性。对于强SQL背景的人而言,这是很难被想象的。但是,如果我们暂时抛弃掉我们的僵化的、限制性的思维,取而代之以一种成长性的思维方式 ——我们所要达成的目标是一种“Schema-Free或Schemaless”的数据模式,也就是无需预先设定数据模式,数据之间的关联性不需要预先定义和了解,随着数据的流入,它们会自然的形成某种关联关系 ——而数据库所需要做的是对应着这些数据“因地制宜”的来处理如何查询与计算。

在过去几十年中,数据库程序员已经被训练得一定要先了解数据模型,不论它是关系型表结构还是实体E-R模式图。了解数据模型当然有它的优点,然而,这也让开发流程变得更加复杂和缓慢。如果读者们还记得上一次你参与的交钥匙解决方案的开发周期有多长了?一个季度、半年、一年还是更久?在一个有8000张表的Oracle数据库中,没有任何一个DBA可以完全掌握所有表之间的关联关系 – 这个时候,我们更愿意把这套脆弱的系统比作一个定时炸弹,而你的所有业务都绑定在其上!

在这里插入图片描述

关于无模式(Schema-Free),我们并不想解释文档型数据库或者宽列据库,尽管它们都多少有一些和图数据库相似的设计理念。我们在下文中会用一些具体的图数据库上的例子来帮助读者理解无模式意味着什么。

二 | 用图数据库的大道至简之法

在图数据库中,逻辑上只有两类基础的数据类型:

· 顶点(Nodes 或Vertices)
· 边(Edges)
在这里插入图片描述

一个顶点具有它自己的ID和属性(标签、类别及其它属性)。边也类似,除了它通常是由两个顶点的顺序决定的(所谓有向图的概念指的是每条边由一个初始顶点对应一个终止顶点,再加上其它属性所构成,例如边的方向、标签、权重等等)。

除了这点儿基础的数据结构,图数据库并不需要任何预先定义的模式或表结构!这种极度简化的理念恰恰和人类如何思考以及存储信息有着很大的相似性 —— 我们通常并不在脑海中设定表结构,我们随机应变。
在这里插入图片描述

现在,让我们看一看一些真实世界场景中的图数据库实现,例如下图中的一个典型的图数据集中的顶点的属性定义,它包含了最初的几个字段的定义例如desc, level, name, type,但是也存在一些动态生成、扩增的字段,例如#cc, #pr, #khop_1等等。如果比照着关系型数据库而言,整个表的结构是动态可调整的。
图数据集中的顶点属性(动态属性)
注意上图中的name和type字段的属性为STRING类型,它可以最大化兼容广谱的数据类型,进而提供最大化的灵活性。顶点之间如何产生关联也无需被预先定义,这样所形成的关联网络也是灵活的。

细心的读者一定会问到,这种灵活性怎么来实现和保证性能优化呢?常识的做法是通过存储与计算分层来实现,例如为了实现极佳的计算性能,数据可以动态的加载进入内存计算(LTE vs. UFE = Load-to-Engine vs. Unload-from-Engine),当然内存计算只是一部分,支持并发计算的数据结构也是必不可少的,有兴趣的读者可以参考笔者之前的文章连载:
《图数据结构的进化》

键值库可以被看做是前-SQL(Pre-SQL在这里表达的是一种相对于SQL而言更原始的特型)的非关系型架构库,图数据库则可被看做是后SQL(Post-SQL在这里表达了一种相对而言的先进性)时代的,真正意义上支持递归式数据结构的数据库。今天的不少NoSQL数据库都试图通过兼容SQL来获得认可,但是在笔者看来,SQL的设计理念是极度表限定的,所谓“表限定”(table-confined),指的是它的整个理念都是限定在二维世界中的,当要进行表连接操作时,就好比要去进入到三维或更高维的空间进行操作,而这也是时常低效和反直觉的,这是基于关系型数据模式的SQL本身的低维属性决定的。

图数据库天然是高维的(除非它的实现是基于关系型数据库或列数据库实现的,那么本质上这种非原生图的设计依然是低维驱动的,它的效率怎么可能会很高呢?),图上面的操作天然的是递归式的,例如广度优先搜索或深度优先搜索。当然,仅仅从语言的兼容性而言,图上面一样也可以支持SQL类操作来保持向关系型用户群的习惯兼容,就像Spark SQL或CQL一样,无论它的意义到底有多大或多长久。

下一讲,让我们一起来看一些通过UQL(Ultipa图查询语言)实现的图上的查询功能。同时,请仔细思考用SQL或是其它NoSQL数据库将如何才能完成同样的任务?
在这里插入图片描述

·未完待续·

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值