SQL的巨大飞跃:MySQL 8.0发布


“你仍在使用SQL-92吗?”是我在“新SQL”演讲中的开篇问题。在我提出这个问题后,竟然有大部分观众坦承仍在使用25年前的技术。而如果我问谁还在使用Windows 3.1,这个版本也是在1992年发布的,则只有少数人举手......而且他们显然在开玩笑。

显然,这种比较不算公平。但它至少表明,围绕较新的SQL标准的技术推广相当缺乏。自SQL-92以来,实际上有五次更新 - 许多开发人员却从未听说过它们。最新版本是SQL:2016。

因此,许多开发人员并不知道自1999年以来,SQL已经不再局限于关系代数或关系模型。SQL:1999引入了在关系代数(横向递归的)没有的运算和打破了第一范式传统解释的类型(arrays!)。

从那时起,19年来,SQL功能是否符合关系思想已不再重要。重要的是,一个功能具有定义明确的语义并解决一个真正的问题。学术方法已经让位于实用的方法。如今SQL标准为几乎所有的数据处理问题提供了一个实用的解决方案。其中一些留在关系域内,而另一些则没有。


注意

在说SQL数据库时不要说关系数据库。SQL实际上不仅仅是关系。

很多开发人员仍然以25年前使用SQL的方式使用SQL,这实在太糟糕了。我认为主要原因是开发人员缺乏知识和兴趣,以及数据库产品对新SQL的支持不足。

我们来看看MySQL的支持程度。考虑到它的市场份额,我认为MySQL对新SQL的轻视极大程度上导致了这种不幸的情况。我曾在2013年的博客文章“MySQL对SQL的影响正如MongoDB对NoSQL一样糟”中谈到了这个观点。信息的关键是“MongoDB是受欢迎的,但它的在同类中不具备大的代表价值,就像MySQL一样”。Joe Celko以不同的方式表达了他对MySQL的看法:“ MySQL不是SQL,它只是从SQL中借用关键字 ”。

你可以在YouTube上的MySQL WAT演讲中看到一些存在问题的SQL解释示例。请注意,该视频是2012年的,使用MySQL 5.5(当时的GA版本)。在那以后,MySQL 5.6和5.7出来了,这大大改善了这种情况。新的安装系统的默认设置现在好多了。

他们真的在考虑如何减轻更改默认值的影响,这一点特别好。例如,当ONLY_FULL_GROUP_BY默认启用时,他们花费更多的时间来实现主要SQL数据库之间最完整的功能依赖性检查:

640?wx_fmt=png

大约在MySQL 5.7发布的同时,我停止了对MySQL的攻击。当然,我在开玩笑。偶尔我还在抨击MySQL ......但从那时起这种抨击就不太容易了。

顺便说一下,你知道MySQL仍然不支持check约束吗?就像在以前的版本中一样,你可以在create table声明中使用check约束,但它们会被忽略。是的没错——没有警告就直接被忽略。连MariaDB都在一年前解决了这个问题。

640?wx_fmt=png

呃,我又在抨击了!抱歉——老习惯很难改变。

尽管如此,在过去的几个版本中,MySQL的开发理念已经发生了明显的变化。发生了什么?你已经知道答案了:自从Oracle通过Sun收购了MySQL后,MySQL正处于新的管理之下。我必须承认:在过去的10年中,这可能是SQL发生的最好的事情,而我就是指SQL而不是MySQL。

我认为单个数据库版本会对整个SQL生态系统产生巨大影响的原因很简单:MySQL是链中最薄弱的一环。如果你强化了这一环,整条链变得更加强大。让我详细说明一下。

MySQL非常受欢迎。据db-engines.com称,它是第二流行的SQL数据库。更重要的是:它是最受欢迎的免费 SQL数据库。这对任何必须使用多个特定SQL数据库的人都有很大的影响。这些通常是制造内容管理系统(CRM),电子商务软件或对象关系映射器(ORM)等产品的软件供应商。由于其广受欢迎,这些厂商通常需要支持MySQL。其中只有少数人咬紧牙关,真正支持多数据库——Java Object Oriented Querying(jOOQ)在这方面确实很突出。许多供应商只限于常规支持的SQL语言中,即MySQL。

受MySQL影响的另一个重要群体是学习SQL的人。他们可以合理地认为最流行的免费SQL数据库是学习的良好基础。他们不知道的是,MySQL将SQL-foo限制为诸多SQL语言中最弱的SQL语言。基于Joe Celko的声明:这些人知道关键字,但不明白它们的真正含义。更糟的是,他们还完全没有听说过现代SQL特性。

上周,当Oracle终于发布了一个普遍可用的版本MySQL 8.0时,这一切都发生了变化。这是一个具有里程碑意义的版本,因为MySQL最终超越了SQL-92以及纯粹的关系教条。在其他一些标准的SQL功能中,MySQL现在支持窗口函数(over)和公用表表达式(with)。毫无疑问,这是两个最重要的Post-SQL-92功能。

软件供应商宣称由于MySQL不支持所以这些功能无法使用的日子已即将过去。如今最流行的免费SQL数据库的文档中也已经包含了窗口函数和公用表表达式。让我大胆地声称:MySQL 8.0是数据库前进的一小步,是SQL进步的一大步。

一切正在变得更好,未来是光明的!由于MySQL已经由Oracle掌握,MySQL的前团队(其中有最初的创建者)创建了MySQL分支MariaDB。显然,他们的策略是增加许多新功能来说服MySQL用户考虑他们的竞争产品。就个人而言,我认为他们会牺牲质量——就像以前的MySQL一样——但这是另一回事。在这里,MariaDB已经使check约束有效达一年之久了,这才是更实质性的。这就产生了一个问题:MySQL还能继续忽略check约束多久?或换句话说,他们还能忍受我的抨击多久;)

除了check约束之外,MariaDB 10.2还引入了窗口函数和通用表表达式(CTE)。那时候,MySQL有一个CTE测试版,但没有窗口功能。MariaDB正在迅速改进。

在10.3中,MariaDB被设置为发布“系统版本化表”。简而言之:一旦激活表格,系统版本控制就会保留更新和删除行的旧版本。默认情况下,查询将像往常一样返回当前版本,但可以使用特殊的语法(as of)来获取旧版本。你可以在MariaDB的公告中阅读更多关于此的信息。

SQL标准中在2011年引入了系统版本管理。现在看来,MariaDB将成为第一个支持它的免费SQL数据库。我希望这是对其他供应商的激励——对于要求供应商支持更新的SQL功能的用户也是如此!

既然新SQL的采用最终得到了一些支持,只剩下一个问题:细致的细节。标准定义的功能有很多子功能,并且由于其数量庞大,通常只支持其中一部分。这意味着仅仅说数据库支持窗口函数是不够的。它实际上支持哪种窗口函数?其中以什么为单位?(行,排列还是组?)这些问题的答案区分了营销噱头和真正强大的功能。

为了让开发人员能够更方便地使用新SQL,我正在测试这些细节,以便突出产品之间的差异。这些测试的结果用和上面一样的表格来展示。本文的其余部分将简要介绍MySQL 8.0中引入的新标准SQL功能,并讨论一些实现上的差异。如你所见,MySQL 8.0在这方面非常好。值得注意的例外是它的JSON功能。

窗函数

SQL分为有窗函数之前的SQL和有窗函数之后的SQL。可以毫不夸张地说,窗函数改变了一切。一旦你理解了窗函数,你就无法想象如果没有它们,你将如何生活。最常见的用法有例如每组找到最好的N行,构建运行总数或移动平均值,以及对连续事件进行分组,只是冰山一角。窗函数是避免自连接的最重要的工具之一。仅此就可以使查询不那么冗余,速度也更快。窗函数非常强大,即使是一些新事物诸如Apache SQL实现(Hive,Impala,Spark),NuoDB和Google BigQuery多年前就引入他们了。所以说MySQL加入得实在是很晚。

下面的表格显示了over从句对某些主要SQL数据库的支持。如你所见,正如PostgreSQL在其新主页上声称的那样,MySQL的实现实际上超过了“世界上最先进的开源关系数据库”的功能。但是,PostgreSQL 11将重新夺回这一领域的领导者地位。

640?wx_fmt=png

MySQL 8.0提供的实际窗口函数集也非常接近现有技术水平:

640?wx_fmt=png

通用表表达式(with [recursive])

MySQL 8.0的下一个主要增强功能是通用表表达式或者说with [recursive]从句。重要的用例是使用单个查询遍历图,生成任意数量的行,将CSV字符串转换为行(反转listagg/ group_concat)或是识字SQL。

MySQL的第一次实现再一次缩小了差距。

640?wx_fmt=png

其他标准SQL功能

除了窗口函数和with从句外,MySQL 8.0还引入了一些其他标准SQL功能。但与前两者相比,这绝不是杀手锏。

640?wx_fmt=png

正如你所看到的,Oracle推动SQL标准对JSON的支持。Oracle数据库和MySQL目前是这方面的领导者(两者都来自同一个供应商!)。json_objectagg和json_arrayagg功能甚至在MySQL 5.7.22得到兼容。但是,值得注意的是,MySQL不遵循这两个函数的标准语法。标准中定义的修饰符(例如order by子句)通常不受支持。Json_objectagg既不识别关键字key和value也不接受冒号(:)来分隔属性名称和值。看起来像是MySQL将它们解析为常规函数调用——而不是标准描述的语法。

同样有趣的是,与Oracle数据库(它们不默认为absent on null)一样,json_arrayagg似乎在处理null值时出错了。在两个据称无关的产品中看到同样的问题总是很有趣。再加上这两个产品来自同一个供应商的事实又增加了一个转折点。

列表中的最后两个功能,grouping函数(与rollup相关)和from从句的列名是解决特定的问题的方法。他们的MySQL 8.0实现基本上与其他数据库一致。

此外,MySQL 8.0还引入了标准的SQL角色。以上表格未列出的原因很简单:表格是基于我对所有这些数据库运行的实际测试。我自行开发的测试框架还不支持需要多个用户的测试用例——目前所有测试都使用默认用户运行,所以我无法测试访问权限。但是我会逐步改善的,请继续关注。

其他显著的增强功能

我想用MySQL 8.0修补程序和与SQL标准无关的改进来结束本文。

其中之一是关于在索引声明中使用desc修饰符:

640?wx_fmt=png

大多数(如果不是全部的话)数据库在索引创建中使用与order by从句相同的逻辑,即默认情况下,列值的顺序是升序。有时需要按照相反的方向对一些索引列进行排序。这时需要在索引中指定desc。以下是MySQL 5.7文档对此的看法:

index_col_name规格可以以ASC或DESC结束。这些关键字可用于将来的扩展,用于指定索引值存储的升序或降序。目前,他们会通过语法分析但同时会被忽略 ; 索引值始终以升序存储。

“他们会通过语法分析但同时会被忽略”?更具体地说:他们会通过语法分析,但就像上文提及的check约束一样不经警告而被忽略。

但是,这已经在MySQL 8.0中解决了。现在有一个警告。只是玩笑!Desc现在仍很特殊。

MySQL 8.0还有许多其他的改进。请参阅“ MySQL 8.0中的新增功能 ”。其他可查阅文章:

  • 直方图(优化器统计)(https://dev.mysql.com/doc/refman/8.0/en/analyze-table.html)

  • InnoDB中的数据字典(另请参见MyISAM的结尾)(https://mysqlserverteam.com/atomic-ddl-in-mysql-8-0/)

  • 隐性索引(https://mysqlserverteam.com/mysql-8-0-invisible-indexes/)

  • 改进后的默认值(不再有latin1_swedish_ci了!)(https://mysqlserverteam.com/new-defaults-in-mysql-8-0/)


∞∞∞



640?wx_fmt=jpeg&wx_lazy=1

IT派 - {技术青年圈} 持续关注互联网、区块链、人工智能领域 640?wx_fmt=jpeg&wx_lazy=1



公众号回复“入群”

邀你加入{ IT派互动粉丝群 }


猜你喜欢

转载自blog.csdn.net/j2iayu7y/article/details/80251989