“你仍在使用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数据库之间最完整的功能依赖性检查:
大约在MySQL 5.7发布的同时,我停止了对MySQL的攻击。当然,我在开玩笑。偶尔我还在抨击MySQL ......但从那时起这种抨击就不太容易了。
顺便说一下,你知道MySQL仍然不支持check约束吗?就像在以前的版本中一样,你可以在create table声明中使用check约束,但它们会被忽略。是的没错——没有警告就直接被忽略。连MariaDB都在一年前解决了这个问题。
呃,我又在抨击了!抱歉——老习惯很难改变。
尽管如此,在过去的几个版本中,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将重新夺回这一领域的领导者地位。
MySQL 8.0提供的实际窗口函数集也非常接近现有技术水平:
通用表表达式(with [recursive])
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.www.dfzx157.com webdriver.support.wait import WebDriverWait
from pyquery import PyQuery as pq
import time
import json
options = webdriver.ChromeOptions(www.yingka178.com)
# 设置无图模式
prefs = {
‘profile.default_content_setting_values‘: {
‘images‘: 2
}
}
options.add_argument(‘--headless‘) # 浏览器隐藏
options.add_argument(‘--disable-gpu‘)
options.add_experimental_option(‘prefs‘, prefs) #设置无图模式
browser = webdriver.Chrome(chrome_options=options)
wait = WebDriverWait(browser,www.meiwanyule.cn 5)
def get_last_page(qq):
try:
url = f‘https://www.douniu157.com user.qzone.qq.com/ www.dejiaylsmile.cn {qq}/311‘
browser.get(url)
try:
browser.find_element(By.www.wmyl11.com NAME, ‘login_www.leyouzaixian2.com frame‘) # 发现登陆的frame
MySQL 8.0的下一个主要增强功能是通用表表达式或者说with [recursive]从句。重要的用例是使用单个查询遍历图,生成任意数量的行,将CSV字符串转换为行(反转listagg/ group_concat)或是识字SQL。
MySQL的第一次实现再一次缩小了差距。
其他标准SQL功能
除了窗口函数和with从句外,MySQL 8.0还引入了一些其他标准SQL功能。但与前两者相比,这绝不是杀手锏。
正如你所看到的,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修饰符:
大多数(如果不是全部的话)数据库在索引创建中使用与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/)
原文地址:https://www.cnblogs.com/qwangxiao/p/9136329.html