溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回

發(fā)布時(shí)間:2021-10-22 16:37:46 來(lái)源:億速云 閱讀:86 作者:iii 欄目:數(shù)據(jù)庫(kù)

本篇內(nèi)容主要講解“分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回”吧!

我們使用數(shù)據(jù)庫(kù),直觀感受上是客戶端發(fā)送一個(gè)  SQL,數(shù)據(jù)庫(kù)把這個(gè)SQL執(zhí)行一下,查出來(lái)數(shù)據(jù)返回給客戶端。但其實(shí)SQL在背后被轉(zhuǎn)換,優(yōu)化,歷經(jīng)許多「磨難」才把結(jié)果給取回來(lái)。

分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回

如上圖, 我們看到是從查詢處理器里經(jīng)過(guò)解析器,優(yōu)化器,才進(jìn)入的執(zhí)行引擎。

今天我們先來(lái)看查詢管理器,后面再重點(diǎn)來(lái)看查詢的優(yōu)化器是怎樣精打細(xì)算的。

查詢管理器

這一部分是數(shù)據(jù)庫(kù)功能體現(xiàn)。在這部分里,會(huì)將寫(xiě)得不好的查詢轉(zhuǎn)換成可以快速執(zhí)行代碼, 然后執(zhí)行它,并將結(jié)果返回給客戶端。這個(gè)過(guò)程會(huì)包含多個(gè)步驟:

  • 首先解析查詢是否是合法的

  • 然后會(huì)將查詢重寫(xiě),去除沒(méi)用的操作符,并做一些預(yù)優(yōu)化

  • 對(duì)查詢優(yōu)化以提升性能,將查詢轉(zhuǎn)換成執(zhí)行和數(shù)據(jù)訪問(wèn)計(jì)劃

  • 編譯查詢計(jì)劃

  • 執(zhí)行

這部分里,對(duì)最后兩點(diǎn)我們不會(huì)說(shuō)太多,相對(duì)來(lái)說(shuō)他倆沒(méi)那么關(guān)鍵。

查詢解析器

每個(gè)SQL語(yǔ)句都會(huì)經(jīng)過(guò)分析器去校驗(yàn)語(yǔ)法是否正確。如果你寫(xiě)錯(cuò)了,解析器會(huì)拒絕查詢。比如你手誤,把SELECT 寫(xiě)成了  SLECT,那直接會(huì)停止在這兒。

此外,還會(huì)檢查關(guān)鍵詞順序是否正確。

然后,查詢SQL中的表名和列名也會(huì)分析,解析器會(huì)通過(guò)數(shù)據(jù)庫(kù)的 metadata 來(lái)檢查以下內(nèi)容:

  • 表是否存在

  • 表中對(duì)應(yīng)的查詢字段是否存在

  • 對(duì)應(yīng)的操作符是不是能作用在指定的列上(比如不能把一個(gè)數(shù)字和字符串比大小,也不能給一個(gè)integer用substring)

之后會(huì)檢查查詢中對(duì)應(yīng)的表你是否有權(quán)限去讀或?qū)?,畢竟這些訪問(wèn)權(quán)限是DBA分配的。

在解析的過(guò)程中, 查詢SQL 會(huì)被轉(zhuǎn)換成數(shù)據(jù)庫(kù)的內(nèi)部表示形式(一般是一棵樹(shù))。如果一切 OK,這個(gè)轉(zhuǎn)換后的內(nèi)容會(huì)發(fā)送給查詢「重寫(xiě)器」

查詢 Rewriter

在這一步,我們拿到了一個(gè)查詢的內(nèi)部表示形式,重寫(xiě)器的目標(biāo)是要:

  • 對(duì)查詢做預(yù)優(yōu)化

  • 避免無(wú)用的操作

  • 幫助優(yōu)化器發(fā)現(xiàn)最佳方案

重寫(xiě)器會(huì)對(duì)查詢執(zhí)行一系列已知的規(guī)則。如果查詢符合某個(gè)規(guī)則的模式,就會(huì)應(yīng)用這個(gè)規(guī)則來(lái)重寫(xiě)查詢。以下是(可選)的規(guī)則:

視圖合并:如果在查詢中使用了視圖,那視圖將會(huì)隨著該視圖的SQL代碼進(jìn)行轉(zhuǎn)換。

子查詢打平:有子查詢的查詢很難優(yōu)化,因此重寫(xiě)器將嘗試修改查詢,甚至刪除子查詢。

例如

SELECT PERSON.* FROM PERSON WHERE PERSON.person_key IN (SELECT MAILS.person_key FROM MAILS WHERE MAILS.mail LIKE 'christophe%');

就會(huì)被這條SQL替換

SELECT PERSON.* FROM PERSON, MAILS WHERE PERSON.person_key = MAILS.person_key and MAILS.mail LIKE 'christophe%';
  • 去除無(wú)用的操作符:如果你用了DISTINCT,但你已經(jīng)有一個(gè)UNIQUE約束以保證數(shù)據(jù)唯一,那DISTINCT關(guān)鍵字就會(huì)被刪除。

  • 消除多余的連接:如果你有兩次相同的連接條件,因?yàn)橐粋€(gè)連接條件被隱藏在視圖中,或者由于傳遞性而導(dǎo)致無(wú)用的連接,則將其刪除。

  • 持續(xù)的算術(shù)評(píng)估:如果查詢是需要計(jì)算的內(nèi)容,那么在重寫(xiě)過(guò)程中將對(duì)其進(jìn)行一次計(jì)算。比如,把WHERE AGE> 10 + 2轉(zhuǎn)換為WHERE  AGE> 12,然后將TODATE(“ 日期”)轉(zhuǎn)換為datetime格式的日期

  • (高級(jí))分區(qū)修正:如果你使用了分區(qū)表,重寫(xiě)器可以找到要使用的分區(qū)。

  • (高級(jí))實(shí)例化視圖重寫(xiě):如果已經(jīng)有了和查詢子集匹配的實(shí)例化視圖,重寫(xiě)器會(huì)檢查該視圖是否是最新視圖,并修改查詢使用實(shí)例化視圖而不是原始表。

  • (高級(jí))自定義規(guī)則:如果你創(chuàng)建了重寫(xiě)查詢的自定義規(guī)則,那重寫(xiě)器會(huì)執(zhí)行這些規(guī)則(高級(jí))Olap轉(zhuǎn)換:分析/窗口函數(shù),星型連接,匯總…也都會(huì)進(jìn)行轉(zhuǎn)換(但是具體是由重寫(xiě)器還是優(yōu)化器完成的取決于數(shù)據(jù)庫(kù),因?yàn)檫@兩個(gè)過(guò)程鄰近)。

這個(gè)重寫(xiě)后的查詢會(huì)發(fā)送給查詢優(yōu)化器,有趣的來(lái)了。

統(tǒng)計(jì)

在進(jìn)入數(shù)據(jù)庫(kù)如何優(yōu)化查詢之前,我們需要先談?wù)劷y(tǒng)計(jì)信息,因?yàn)闆](méi)有統(tǒng)計(jì)信息,數(shù)據(jù)庫(kù)就會(huì)很傻。如果你不告訴數(shù)據(jù)庫(kù)分析自己的數(shù)據(jù),它不會(huì)這樣做,而且會(huì)做出錯(cuò)誤的假設(shè)。

那數(shù)據(jù)庫(kù)需要什么信息呢?

我們大概說(shuō)一下論數(shù)據(jù)庫(kù)和操作系統(tǒng)如何存儲(chǔ)數(shù)據(jù)的。他們使用的最小單位稱為頁(yè)或塊(默認(rèn)為4或8 KB)。也就是說(shuō),如果你只需要1  KB,也會(huì)占一頁(yè)。如果頁(yè)面占用8 KB,那就會(huì)浪費(fèi)7 KB。

回到統(tǒng)計(jì)來(lái),當(dāng)你要求數(shù)據(jù)庫(kù)獲取統(tǒng)計(jì)信息時(shí),它會(huì)計(jì)算這些內(nèi)容:

  • 一個(gè)表中的行或頁(yè)的數(shù)量

  • 一個(gè)表里的每一列

    • 單獨(dú)的數(shù)據(jù)內(nèi)容

    • 數(shù)據(jù)的長(zhǎng)度(最小,最大,平均)

    • 數(shù)據(jù)區(qū)間信息(最小、最大、平均)

  • 表的索引信息

這些統(tǒng)計(jì)信息會(huì)幫助優(yōu)化器更好的預(yù)估查詢中磁盤I/O,CPU以及內(nèi)存的使用。

每一列的統(tǒng)計(jì)信息都很重要。比如一個(gè) PERSON 表,需要在 LAST_NAME,  FIRST_NAME兩列做連接,通過(guò)統(tǒng)計(jì),數(shù)據(jù)庫(kù)能知道FIRST_NAME這一列共多少個(gè)不同的值,LAST_NAME有多少個(gè)不同的值。所以數(shù)據(jù)庫(kù)會(huì)使用LAST_NAME,FIRST_NAME來(lái)連接,而不是FIRST_NAME,LAST_NAME,因?yàn)長(zhǎng)AST_NAME不太可能相同,會(huì)少產(chǎn)生數(shù)據(jù)。大多數(shù)情況下,數(shù)據(jù)庫(kù)的前兩三個(gè)字符比較  LAST_NAME就足夠了。

當(dāng)然這些是基本的統(tǒng)計(jì)信息,你也可以讓數(shù)據(jù)庫(kù)計(jì)算 histograms  這種更高階的統(tǒng)計(jì)數(shù)據(jù)。最常使用的值,質(zhì)量等等,通過(guò)這些附加信息,可以幫助數(shù)據(jù)庫(kù)找到更高效的查詢計(jì)劃,特別是像等值查詢,以及范圍查詢這種。因?yàn)閿?shù)據(jù)庫(kù)已經(jīng)知道這種情況下有多少條記錄。

這些統(tǒng)計(jì)信息記錄在數(shù)據(jù)庫(kù)的元數(shù)據(jù)中。因此也是需要花時(shí)間不斷更新的。這也是為啥在大多數(shù)數(shù)據(jù)庫(kù)里他都不自動(dòng)更新。

到此,相信大家對(duì)“分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

sql
AI