1. 程式人生 > >SQL的巨大飛躍:MySQL 8.0發布

SQL的巨大飛躍:MySQL 8.0發布

G1 測試 mysql用戶 局限 數據庫 jhh sqlserver 升序 事情

“你仍在使用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/)

SQL的巨大飛躍:MySQL 8.0發布