本篇內(nèi)容主要講解“分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“分享一次數(shù)據(jù)庫(kù)SQL查詢的數(shù)次輪回”吧!
成都創(chuàng)新互聯(lián)專注于企業(yè)營(yíng)銷型網(wǎng)站、網(wǎng)站重做改版、金山網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5、電子商務(wù)商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為金山等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
我們使用數(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)。
如上圖, 我們看到是從查詢處理器里經(jīng)過(guò)解析器,優(yōu)化器,才進(jìn)入的執(zhí)行引擎。
今天我們先來(lái)看查詢管理器,后面再重點(diǎn)來(lái)看查詢的優(yōu)化器是怎樣精打細(xì)算的。
查詢管理器
這一部分是數(shù)據(jù)庫(kù)功能體現(xiàn)。在這部分里,會(huì)將寫得不好的查詢轉(zhuǎn)換成可以快速執(zhí)行代碼, 然后執(zhí)行它,并將結(jié)果返回給客戶端。這個(gè)過(guò)程會(huì)包含多個(gè)步驟:
首先解析查詢是否是合法的
然后會(huì)將查詢重寫,去除沒(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ǔ)法是否正確。如果你寫錯(cuò)了,解析器會(huì)拒絕查詢。比如你手誤,把SELECT 寫成了 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ā)送給查詢「重寫器」
查詢 Rewriter
在這一步,我們拿到了一個(gè)查詢的內(nèi)部表示形式,重寫器的目標(biāo)是要:
對(duì)查詢做預(yù)優(yōu)化
避免無(wú)用的操作
幫助優(yōu)化器發(fā)現(xiàn)最佳方案
重寫器會(huì)對(duì)查詢執(zhí)行一系列已知的規(guī)則。如果查詢符合某個(gè)規(guī)則的模式,就會(huì)應(yīng)用這個(gè)規(guī)則來(lái)重寫查詢。以下是(可選)的規(guī)則:
視圖合并:如果在查詢中使用了視圖,那視圖將會(huì)隨著該視圖的SQL代碼進(jìn)行轉(zhuǎn)換。
子查詢打平:有子查詢的查詢很難優(yōu)化,因此重寫器將嘗試修改查詢,甚至刪除子查詢。
例如
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)容,那么在重寫過(guò)程中將對(duì)其進(jìn)行一次計(jì)算。比如,把WHERE AGE> 10 + 2轉(zhuǎn)換為WHERE AGE> 12,然后將TODATE(“ 日期”)轉(zhuǎn)換為datetime格式的日期
(高級(jí))分區(qū)修正:如果你使用了分區(qū)表,重寫器可以找到要使用的分區(qū)。
(高級(jí))實(shí)例化視圖重寫:如果已經(jīng)有了和查詢子集匹配的實(shí)例化視圖,重寫器會(huì)檢查該視圖是否是最新視圖,并修改查詢使用實(shí)例化視圖而不是原始表。
(高級(jí))自定義規(guī)則:如果你創(chuàng)建了重寫查詢的自定義規(guī)則,那重寫器會(huì)執(zhí)行這些規(guī)則(高級(jí))Olap轉(zhuǎn)換:分析/窗口函數(shù),星型連接,匯總…也都會(huì)進(jìn)行轉(zhuǎn)換(但是具體是由重寫器還是優(yōu)化器完成的取決于數(shù)據(jù)庫(kù),因?yàn)檫@兩個(gè)過(guò)程鄰近)。
這個(gè)重寫后的查詢會(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í)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!