通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL-Other_第1頁
通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL-Other_第2頁
通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL-Other_第3頁
通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL-Other_第4頁
通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL-Other_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL第1章性能調(diào)整綜述第2章有效的使用設(shè)計第3章SQL語句處理的過程第4章ORACLE勺優(yōu)化器第5章ORACLE勺執(zhí)行計劃訪問路徑(方法)-accesspath表之間的連接如何產(chǎn)生執(zhí)行計劃如何分析執(zhí)行計劃如何干預(yù)執(zhí)行計劃-使用hints提示具體案例分析第1章性能調(diào)整綜述Oracle數(shù)據(jù)庫是高度可調(diào)的數(shù)據(jù)庫產(chǎn)品。本章描述調(diào)整的過程和那些人員應(yīng)和Oracle服務(wù)器的調(diào)整有關(guān),以及和調(diào)整相關(guān)聯(lián)的操作系統(tǒng)硬件和軟件。本章包括以下方面:誰來調(diào)整系統(tǒng)?什么時候調(diào)整?建立有效調(diào)整的目標(biāo)在設(shè)計和開發(fā)時的調(diào)整調(diào)整產(chǎn)品系統(tǒng)監(jiān)控產(chǎn)品系統(tǒng)誰來調(diào)整系統(tǒng):為了有效地調(diào)整系統(tǒng),若干類人員必

2、須交換信息并牽涉到系統(tǒng)調(diào)整中,例如:使用設(shè)計人員必須傳達(dá)使用系統(tǒng)的設(shè)計,使得每個人都清楚使用中的數(shù)據(jù)流動.使用開發(fā)人員必須傳達(dá)他們選擇的實現(xiàn)策略,使得語句調(diào)整的過程中能快速、容易地識別有問題的使用模塊和可疑的SQl語句.數(shù)據(jù)庫管理人員必須仔細(xì)地監(jiān)控系統(tǒng)活動并提供它們的資料,使得異常的系統(tǒng)性能可被快速得識別和糾正.硬件/軟件管理人員必須傳達(dá)系統(tǒng)的硬件、軟件配置并提供它們的資料,使得相關(guān)人員能有效地設(shè)計和管理系統(tǒng)。簡而言之,和系統(tǒng)涉及的每個人都在調(diào)整過程中起某些作用,當(dāng)上面提及的那些人員傳達(dá)了系統(tǒng)的特性并提供了它們的資料,調(diào)整就能相對的容易和更快一些。不幸的是,事實上的結(jié)果是:數(shù)據(jù)庫管理員對調(diào)整負(fù)

3、有全部或主要的責(zé)任。但是,數(shù)據(jù)庫管理員很少有合適的系統(tǒng)方面的資料,而且,在很多情況下,數(shù)據(jù)庫管理員往往是在實施階段才介入數(shù)據(jù)庫,這就給調(diào)整工作帶來許多負(fù)面的影響,因為在設(shè)計階段的缺陷是不能通過DBA的調(diào)整而得以解決,而設(shè)計階段的缺陷往往對數(shù)據(jù)庫性能造成極大的影響。其實,在真正成熟的開發(fā)環(huán)境下,開發(fā)人員作為純代碼編寫人員時,對性能的影響最小,此時大部分的工作應(yīng)由使用設(shè)計人員完成,而且數(shù)據(jù)庫管理員往往在前期的需求管理階段就介入,為設(shè)計人員提供必要的技術(shù)支持。調(diào)整并不是數(shù)據(jù)庫管理員的專利,相反大部分應(yīng)該是設(shè)計人員和開發(fā)人員的工作,這就需要設(shè)計人員和開發(fā)人員具體必要的數(shù)據(jù)庫知識,這樣才能組成一個高效的

4、團隊,然而事實上往往并非如此。什么時候作調(diào)整?多數(shù)人認(rèn)為當(dāng)用戶感覺性能差時才進(jìn)行調(diào)整,這對調(diào)整過程中使用某些最有效的調(diào)整策略來說往往是太遲了。此時,如果你不愿意重新設(shè)計使用的話,你只能通過重新分配內(nèi)存(調(diào)整SGA)和調(diào)整I/O的辦法或多或少地提高性能。Oracle提供了許多特性,這些特性只有使用到正確地設(shè)計的系統(tǒng)中時才能夠很大地提高性能。使用設(shè)計人員需要在設(shè)計階段設(shè)置使用的性能期望值。然后在設(shè)計和開發(fā)期間,使用設(shè)計人員應(yīng)考慮哪些Oracle特性可以對系統(tǒng)有好處,并使用這些特性。通過良好的系統(tǒng)設(shè)計,你就可以在使用的生命周期中消除性能調(diào)整的代價和挫折。當(dāng)然,即使在設(shè)計很好的系統(tǒng)中,也可能有性能降低

5、。但這些性能降低應(yīng)該是可控的和可以預(yù)見的。調(diào)整目標(biāo)不管你正在設(shè)計或維護(hù)系統(tǒng),你應(yīng)該建立專門的性能目標(biāo),它使你知道何時要作調(diào)整。如果你試圖胡亂地改動初始化參數(shù)或SQl語句,你可能會浪費調(diào)整系統(tǒng)的時間,而且無什么大的收益。調(diào)整你的系統(tǒng)的最有效方法如下:當(dāng)設(shè)計系統(tǒng)時考慮性能調(diào)整操作系統(tǒng)的硬件和軟件識別性能瓶頸確定問題的原因采取糾正的動作當(dāng)你設(shè)計系統(tǒng)時,制定專門的目標(biāo);例如,響應(yīng)時間小于3秒。當(dāng)使用不能滿足此目標(biāo)時,識別造成變慢的瓶頸(例如,I/O競爭),確定原因,采取糾正動作。在開發(fā)期間,你應(yīng)測試使用研究,確定在采取使用之前是否滿足設(shè)計的性能目標(biāo)。當(dāng)你正在維護(hù)生產(chǎn)庫系統(tǒng)時,有多種快速有效的方法來識別

6、性能瓶頸。不管怎樣,調(diào)整通常是一系列開銷。一旦你已確定了瓶頸,你可能要犧牲一些其它方面的指標(biāo)來達(dá)到所要的結(jié)果。例如,如果I/O有問題,你可能需要更多內(nèi)存或磁盤。如果不可能買,你可能要限制系統(tǒng)的并發(fā)性,來獲取所需的性能。然而,如果你已經(jīng)明確地定義了性能的目標(biāo),那用什么來交換高性能的決策就變的很容易的,因為你已經(jīng)確定了哪些方面是最重要的,如過我的目標(biāo)為高性能,可能犧牲一些空間資源。隨著使用的越來越龐大,硬件性能的提高,全面的調(diào)整使用逐漸變成代價高昂的行為,在這樣情況下,要取得最大的投入/效率之比,較好的辦法是調(diào)整使用的關(guān)鍵部分,使其達(dá)到比較高的性能,這樣從總體上來說,整個系統(tǒng)的性能也是比較高的。這

7、也就是有名的20/80原則,調(diào)整使用的20%(關(guān)鍵部分),能解決80%的問題。在設(shè)計和開發(fā)系統(tǒng)時作調(diào)整良好設(shè)計的系統(tǒng)可以防止在使用生命周期中產(chǎn)生性能問題。系統(tǒng)設(shè)計人員和使用開發(fā)人員必須了解Oracle的查詢處理機制以便寫出高效的SQI語句。第2章有效的使用設(shè)計討論了你的系統(tǒng)中各種可用的配置,以及每種配置更適合哪種類型的使用?!暗?章優(yōu)化器討論了Oracle的查詢優(yōu)化器,以及如何寫語句以獲取最快的結(jié)果。當(dāng)設(shè)計你的系統(tǒng)時,使用下列優(yōu)化性能的準(zhǔn)則:消除客戶機服務(wù)器使用中不必要的網(wǎng)絡(luò)傳輸。-使用存儲過程。*使用適合你系統(tǒng)的相應(yīng)Oracle服務(wù)器選件(例如,并行查詢或分布式數(shù)據(jù)庫)衣除非你的使用有特殊的

8、需要,否則使用缺省的Oracle鎖。利用數(shù)據(jù)庫記住使用模塊,以便你能以每個模塊為基礎(chǔ)來追蹤性能。選擇你的數(shù)據(jù)塊的最佳大小。-原則上來說大一些的性能較好。分布你的數(shù)據(jù),使得一個節(jié)點使用的數(shù)據(jù)本地存貯在該節(jié)點中。調(diào)整產(chǎn)品系統(tǒng)本節(jié)描述對使用系統(tǒng)快速、容易地找出性能瓶頸,并決定糾正動作的方法。這種方法依賴于對Oracle服務(wù)器體系結(jié)構(gòu)和特性的了解程度。在試圖調(diào)整你的系統(tǒng)前,你應(yīng)熟悉Oracle調(diào)整的內(nèi)容。為調(diào)整你已有的系統(tǒng),遵從下列步驟:調(diào)整操作系統(tǒng)的硬件和軟件*通過查詢V$SESSION_WAP視圖,識別性能的瓶頸,這個動態(tài)性能視圖列出了造成會話(session)等待的事件。*通過分析V$SESSI

9、ON_WA沖的數(shù)據(jù),決定瓶頸的原因。糾正存在的問題。監(jiān)控使用系統(tǒng)這主要是通過監(jiān)控oracle的動態(tài)視圖來完成。各種有用的動態(tài)視圖:如v$session_wait,v$session_event等。第2章有效的使用設(shè)計我們通常將最常用的使用分為2種類型:聯(lián)機事務(wù)處理類型(OLTP)決策支持系統(tǒng)(DSS。聯(lián)機事務(wù)處理(OLTP)該類型的使用是高吞吐量,插入、更新、刪除操作比較多的系統(tǒng),這些系統(tǒng)以不斷增長的大容量數(shù)據(jù)為特征,它們提供給成百用戶同時存取,典型的OLTP系統(tǒng)是訂票系統(tǒng),銀行的業(yè)務(wù)系統(tǒng),訂單系統(tǒng)。OTLP的主要目標(biāo)是可用性、速度、并發(fā)性和可恢復(fù)性。當(dāng)設(shè)計這類系統(tǒng)時,必須確保大量的并發(fā)用戶不

10、能干擾系統(tǒng)的性能。還需要避免使用過量的索引和cluster表,因為這些結(jié)構(gòu)會使插入和更新操作變慢。決策支持(DSS)該類型的使用將大量信息進(jìn)行提取形成報告,協(xié)助決策者作出正確的判斷。典型的情況是:決策支持系統(tǒng)將OLTP使用收集的大量數(shù)據(jù)進(jìn)行查詢。典型的使用為客戶行為分析系統(tǒng)(超市,保險等)。決策支持的關(guān)鍵目標(biāo)是速度、精確性和可用性。該種類型的設(shè)計往往和OLTP設(shè)計的理念背道而馳,一般建議使用數(shù)據(jù)冗余、大量索引、clustertable、并行查詢等。近年來,該類型的使用逐漸和OLAP數(shù)據(jù)倉庫緊密的聯(lián)系在一起,形成的一個新的使用方向。第3章SQL語句處理的過程在調(diào)整之前我們需要了解一些背景知識,只

11、有知道這些背景知識,我們才能更好的去調(diào)整sql語句。本節(jié)介紹了SQL語句處理的基本過程,主要包括:查詢語句處理DML語句處理(insert,update,delete)DDL語句處理(create.,drop.,alter.,)事務(wù)控制(commit,rollback)SQL語句的執(zhí)行過程(SQLStatementExecution)在某些情況下,Oracle運行sql的過程可能和下面列出的各個階段的順序有所不同。如DEFINE階段可能在FETCH階段之前,這主要依賴你如何書寫代碼。對許多oracle的工具來說,其中某些階段會自動執(zhí)行。絕大多數(shù)用戶不需要關(guān)心各個階段的細(xì)節(jié)問題,然而,知道執(zhí)行的

12、各個階段還是有必要的,這會幫助你寫出更高效的SQL語句來,而且還可以讓你猜測出性能差的SQL語句主要是由于哪一個階段造成的,然后我們針對這個具體的階段,找出解決的辦法。DML語句的處理本節(jié)給出一個例子來說明在DML語句處理的各個階段到底發(fā)生了什么事情。假設(shè)你使用Pro*C程序來為指定部門的所有職員增加工資。程序已經(jīng)連到正確的用戶,你可以在你的程序中嵌入如下的SQL語句:EXECSQLUPDATEemployeesSETsalary=1.10*salaryWHEREdepartment_id=:var_department_id;var_department_id是程序變量,里面包含部門號,我們

13、要修改該部門的職員的工資。當(dāng)這個SQL語句執(zhí)行時,使用該變量的值。每種類型的語句都需要如下階段:第1步:CreateaCursor創(chuàng)建游標(biāo)第2步:ParsetheStatement分析語句第5步:BindAnyVariables綁定變量第7步:RuntheStatement運行語句第9步:ClosetheCursor關(guān)閉游標(biāo)如果使用了并行功能,還會包含下面這個階段:第6步:ParallelizetheStatement并行執(zhí)行語句如果是查詢語句,則需要以下幾個額外的步驟,如圖3所示:第3步:DescribeResultsofaQuery描述查詢的結(jié)果集第4步:DefineOutputofaQu

14、ery定義查詢的輸出數(shù)據(jù)第8步:FetchRowsofaQuery取查詢出來的行下面具體說一下每一步中都發(fā)生了什么事情:.第1步:創(chuàng)建游標(biāo)(CreateaCursor)由程序接口調(diào)用創(chuàng)建一個游標(biāo)(cursor)。任何SQL語句都會創(chuàng)建它,特別在運行DML語句時,都是自動創(chuàng)建游標(biāo)的,不需要開發(fā)人員干預(yù)。多數(shù)使用中,游標(biāo)的創(chuàng)建是自動的。然而,在預(yù)編譯程序(pro*c)中游標(biāo)的創(chuàng)建,可能是隱含的,也可能顯式的創(chuàng)建。在存儲過程中也是這樣的。第2步:分析語句(ParsetheStatement)在語法分析期間,SQL語句從用戶進(jìn)程傳送到Oracle,SQL句經(jīng)語法分析后,SQL語句本身和分析的信息都被裝

15、入到共享SQL區(qū)。在該階段中,可以解決許多類型的錯誤。語法分析分別執(zhí)行下列操作:*翻譯SQL語句,驗證它是合法的語句,即書寫正確實現(xiàn)數(shù)據(jù)字典的查找,以驗證是否符合表和列的定義*在所要求的對象上獲取語法分析鎖,使得在語句的語法分析過程中不改變這些對象的定義*驗證為存取所涉及的模式對象所需的權(quán)限是否滿足*決定此語句最佳的執(zhí)行計劃*將它裝入共享SQL區(qū)*對分布的語句來說,把語句的全部或部分路由到包含所涉及數(shù)據(jù)的遠(yuǎn)程節(jié)點八、以上任何一步出現(xiàn)錯誤,都將導(dǎo)致語句報錯,中止執(zhí)行。只有在共享池中不存在等價SQL語句的情況下,才對SQL語句作語法分析。在這種情況下,數(shù)據(jù)庫內(nèi)核重新為該語句分配新的共享SQL區(qū),并

16、對語句進(jìn)行語法分析。進(jìn)行語法分析需要耗費較多的資源,所以要盡量避免進(jìn)行語法分析,這是優(yōu)化的技巧之一。語法分析階段包含了不管此語句將執(zhí)行多少次,而只需分析一次的處理要求。Oracle只對每個SQL語句翻譯一次,在以后再次執(zhí)行該語句時,只要該語句還在共享SQL區(qū)中,就可以避免對該語句重新進(jìn)行語法分析,也就是此時可以直接使用其對應(yīng)的執(zhí)行計劃對數(shù)據(jù)進(jìn)行存取。這主要是通過綁定變量(bindvariable)實現(xiàn)的,也就是我們常說的共享SQL后面會給出共享SQL的概念。雖然語法分析驗證了SQL語句的正確性,但語法分析只能識別在SQL語句執(zhí)行之前所能發(fā)現(xiàn)的錯誤(如書寫錯誤、權(quán)限不足等)。因此,有些錯誤通過語

17、法分析是抓不到的。例如,在數(shù)據(jù)轉(zhuǎn)換中的錯誤或在數(shù)據(jù)中的錯(如企圖在主鍵中插入重復(fù)的值)以及死鎖等均是只有在語句執(zhí)行階段期間才能遇到和報告的錯誤或情況。查詢語句的處理查詢和其它類型的SQL語句不同,因為在成功執(zhí)行后作為結(jié)果將返回數(shù)據(jù)。其它語句只是簡單地返回成功或失敗,而查詢則能返回一行或許多行數(shù)據(jù)。查詢的結(jié)果均采用表格形式,結(jié)果行被一次一行或者批量地被檢索出來。從這里我們可以得知批量的fetch數(shù)據(jù)可以降低網(wǎng)絡(luò)開銷,所以批量的fetch也是優(yōu)化的技巧之一。有些問題只和查詢處理相關(guān),查詢不僅僅指SELECTS句,同樣也包括在其它SQL語句中的隱含查詢。例如,下面的每個語句都需要把查詢作為它執(zhí)行的一

18、部分:INSERTINTOtableSELECT.UPDATEtableSETx=yWHERE.DELETEFROMtableWHERE.CREATEtableASSELECT.具體來說,查詢要求讀一致性可能使用回滾段作中間處理可能要求SQL語句處理描述、定義和取數(shù)據(jù)階段第3步:描述查詢結(jié)果(DescribeResultsofaQuery)描述階段只有在查詢結(jié)果的各個列是未知時才需要;例如,當(dāng)查詢由用戶交互地輸入需要輸出的列名。在這種情況要用描述階段來決定查詢結(jié)果的特征(數(shù)據(jù)類型,長度和名字)。第4步:定義查詢的輸出數(shù)據(jù)(DefineOutputofaQuery)在查詢的定義階段,你指定和查詢

19、出的列值對應(yīng)的接收變量的位置、大小和數(shù)據(jù)類型,這樣我們通過接收變量就可以得到查詢結(jié)果。如果必要的話,Oracle會自動實現(xiàn)數(shù)據(jù)類型的轉(zhuǎn)換。這是將接收變量的類型和對應(yīng)的列類型相比較決定第5步:綁定變量(BindAnyVariables)此時,Oracle知道了SQL語句的意思,但仍沒有足夠的信息用于執(zhí)行該語句。Oracle需要得到在語句中列出的所有變量的值。在該例中,Oracle需要得到對department_id列進(jìn)行限定的值。得到這個值的過程就叫綁定變量(bindingvariables)此過程稱之為將變量值捆綁進(jìn)來。程序必須指出可以找到該數(shù)值的變量名(該變量被稱為捆綁變量,變量名實質(zhì)上是一

20、個內(nèi)存地址,相當(dāng)于指針)。使用的最終用戶可能并沒有發(fā)覺他們正在指定捆綁變量,因為Oracle的程序可能只是簡單地指示他們輸入新的值,其實這一切都在程序中自動做了。因為你指定了變量名,在你再次執(zhí)行之前無須重新捆綁變量。你可以改變綁定變量的值,而Oracle在每次執(zhí)行時,僅僅使用內(nèi)存地址來查找此值。如果Oracle需要實現(xiàn)自動數(shù)據(jù)類型轉(zhuǎn)換的話(除非它們是隱含的或缺省的),你還必須對每個值指定數(shù)據(jù)類型和長度。關(guān)于這些信息可以參考o(jì)racle的相關(guān)文檔,如OracleCallInterfaceProgrammersGuide第6步:并行執(zhí)行語句(ParallelizetheStatement)ORAC

21、LED以在SELECTS,INSERTS,UPDATES,MERGES,DELETS句中執(zhí)行相應(yīng)并行查詢操作,對于某些DDL操作,如創(chuàng)建索引、用子查詢創(chuàng)建表、在分區(qū)表上的操作,也可以執(zhí)行并行操作。并行化可以導(dǎo)致多個服務(wù)器進(jìn)程(oracleserverprocesses)為同一個SQL語句工作,使該SQL語句可以快速完成,但是會耗費更多的資源,所以除非很有必要,否則不要使用并行查詢。第7步:執(zhí)行語句(RuntheStatement)到了現(xiàn)在這個時候,Oracle擁有所有需要的信息和資源,因此可以真正運行SQL語句了。如果該語句為SELEC查詢或INSERT語句,則不需要鎖定任何行,因為沒有數(shù)據(jù)需

22、要被改變。然而,如果語句為UPDAT或DELETED句,貝U該語句影響的所有行都被鎖定,防止該用戶提交或回滾之前,別的用戶對這些數(shù)據(jù)進(jìn)行修改。這保證了數(shù)據(jù)的一致性。對于某些語句,你可以指定執(zhí)行的次數(shù),這稱為批處理(arrayprocessing)。指定執(zhí)行N次,則綁定變量和定義變量被定義為大小為N的數(shù)組的開始位置,這種方法可以減少網(wǎng)絡(luò)開銷,也是優(yōu)化的技巧之一。第8步:取出查詢的行(FetchRowsofaQuery)在fetch階段,行數(shù)據(jù)被取出來,每個后續(xù)的存取操作檢索結(jié)果集中的下一行數(shù)據(jù),直到最后一行被取出來。上面提到過,批量的fetch是優(yōu)化的技巧之一。第9步:關(guān)閉游標(biāo)(Closethe

23、Cursor)SQL語句處理的最后一個階段就是關(guān)閉游標(biāo)DDL語句的處理(DDLStatementProcessing)DDL語句的執(zhí)行不同和DML語句和查詢語句的執(zhí)行,這是因為DDL語句執(zhí)行成功后需要對數(shù)據(jù)字典數(shù)據(jù)進(jìn)行修改。對于DDL語句,語句的分析階段實際上包括分析、查找數(shù)據(jù)字典信息和執(zhí)行。事務(wù)管理語句、會話管理語句、系統(tǒng)管理語句只有分析和執(zhí)行階段,為了重新執(zhí)行該語句,會重新分析和執(zhí)行該語句。事務(wù)控制(ControlofTransactions)一般來說,只有使用ORACL編程接口的使用設(shè)計人員才關(guān)心操作的類型,并把相關(guān)的操作組織在一起,形成一個事務(wù)。一般來說,我門必須定義事務(wù),這樣在一個邏

24、輯單元中的所有工作可以同時被提交或回滾,保證了數(shù)據(jù)的一致性。一個事務(wù)應(yīng)該由邏輯單元中的所有必須部分組成,不應(yīng)該多一個,也不應(yīng)該少一個。在事務(wù)開始和結(jié)束的這段時間內(nèi),所有被引用表中的數(shù)據(jù)都應(yīng)該在一致的狀態(tài)(或可以被回溯到一致的狀態(tài))事務(wù)應(yīng)該只包含可以對數(shù)據(jù)進(jìn)行一致更改(oneconsistentchangetothedata)的SQL語句例如,在兩個帳號之間的轉(zhuǎn)帳(這是一個事務(wù)或邏輯工作單元),應(yīng)該包含從一個帳號中借錢(由一個SQL完成),然后將借的錢存入另一個帳號(由另一個SQL完成)。這2個操作作為一個邏輯單元,應(yīng)該同時成功或同時失敗。其它不相關(guān)的操作,如向一個帳戶中存錢,不應(yīng)該包含在這個轉(zhuǎn)

25、帳事務(wù)中。在設(shè)計使用時,除了需要決定哪種類型的操作組成一個事務(wù)外,還需要決定使用BEGIN_DISCRETE_TRANSAC存儲過程是否對提高小的、非分布式的事務(wù)的性能有作用。第4章ORACLE的優(yōu)化器優(yōu)化器有時也被稱為查詢優(yōu)化器,這是因為查詢是影響數(shù)據(jù)庫性能最主要的部分,不要以為只有SELECTS句是查詢。實際上,帶有任何WHER條件的DML(INSER、UPDAT、DELETE語句中都包含查詢要求,在后面的文章中,當(dāng)說到查詢時,不一定只是指SELECTS句,也有可能指DML語句中的查詢部分。優(yōu)化器是所有關(guān)系數(shù)據(jù)庫引擎中的最神秘、最富挑戰(zhàn)性的部件之一,從性能的角度看也是最重要的部分,它性能的

26、高低直接關(guān)系到數(shù)據(jù)庫性能的好壞。我們知道,SQL語句同其它語言(如C語言)的語句不一樣,它是非過程化(non-procedural)的語句,即當(dāng)你要取數(shù)據(jù)時,不需要告訴數(shù)據(jù)庫通過何種途徑去取數(shù)據(jù),如到底是通過索引取數(shù)據(jù),還是應(yīng)該將表中的每行數(shù)據(jù)都取出來,然后再通過一一比較的方式取數(shù)據(jù)(即全表掃描),這是由數(shù)據(jù)庫的優(yōu)化器決定的,這就是非過程化的含義,也就是說,如何取數(shù)據(jù)是由優(yōu)化器決定,而不是使用開發(fā)者通過編程決定。在處理SQL勺SELECTUPDATENSERT或DELETED句時,Oracle必須訪問語句所涉及的數(shù)據(jù),Oracle的優(yōu)化器部分用來決定訪問數(shù)據(jù)的有效路徑,使得語句執(zhí)行所需勺I/O

27、和處理時間最小。為了實現(xiàn)一個查詢,內(nèi)核必須為每個查詢定制一個查詢策略,或為取出符合條件勺數(shù)據(jù)生成一個執(zhí)行計劃(executionplan)。典型勺,對于同一個查詢,可能有幾個執(zhí)行計劃都符合要求,都能得到符合條件勺數(shù)據(jù)。例如,參和連接勺表可以有多種不同勺連接方法,這取決于連接條件和優(yōu)化器采用勺連接方法。為了在多個執(zhí)行計劃中選擇最優(yōu)勺執(zhí)行計劃,優(yōu)化器必須使用一些實際勺指標(biāo)來衡量每個執(zhí)行計劃使用的資源(I/O次數(shù)、CPU等),這些資源也就是我們所說的代價(cost)o如果一個執(zhí)行計劃使用的資源多,我們就說使用執(zhí)行計劃的代價大。以執(zhí)行計劃的代價大小作為衡量標(biāo)準(zhǔn),優(yōu)化器選擇代價最小的執(zhí)行計劃作為真正執(zhí)行

28、該查詢的執(zhí)行計劃,并拋棄其它的執(zhí)行計劃。在ORACL的發(fā)展過程中,一共開發(fā)過2種類型的優(yōu)化器:基于規(guī)則的優(yōu)化器和基于代價的優(yōu)化器。這2種優(yōu)化器的不同之處關(guān)鍵在于:取得代價的方法和衡量代價的大小不同?,F(xiàn)對每種優(yōu)化器做一下簡單的介紹:基于規(guī)則的優(yōu)化器-RuleBased(Heuristic)Optimization(簡稱RBO):在ORACLE之前,主要是使用基于規(guī)則的優(yōu)化器。ORACL在基于規(guī)則的優(yōu)化器中采用啟發(fā)式的方法(HeuristicApproach)或規(guī)則(Rules)來生成執(zhí)行計劃。例如,如果一個查詢的where條件(whereclause)包含一個謂詞(predicate,其實就是一

29、個判斷條件,如”=”,“”,”等),而且該謂詞上引用的列上有有效索引,那么優(yōu)化器將使用索引訪問這個表,而不考慮其它因素,如表中數(shù)據(jù)的多少、表中數(shù)據(jù)的易變性、索引的可選擇性等。此時數(shù)據(jù)庫中沒有關(guān)于表和索引數(shù)據(jù)的統(tǒng)計性描述,如表中有多上行,每行的可選擇性等。優(yōu)化器也不考慮實例參數(shù),如multiblocki/o、可用排序內(nèi)存的大小等,所以優(yōu)化器有時就選擇了次優(yōu)化的計劃作為真正的執(zhí)行計劃,導(dǎo)致系統(tǒng)性能不高。如,對于select*fromempwheredeptno=10這個查詢來說,如果是使用基于規(guī)則的優(yōu)化器,而且deptno列上有有效的索引,則會通過deptno列上的索引來訪問emp表。在絕大多數(shù)情

30、況下,這是比較高效的,但是在一些特殊情況下,使用索引訪問也有比較低效的時候,現(xiàn)舉例說明:emp表比較小,該表的數(shù)據(jù)只存放在幾個數(shù)據(jù)塊中。此時使用全表掃描比使用索引訪問emp表反而要好。因為表比較小,極有可能數(shù)據(jù)全在內(nèi)存中,所以此時做全表掃描是最快的。而如果使用索引掃描,需要先從索引中找到符合條件記錄的rowid,然后再一一根據(jù)這些rowid從emp中將數(shù)據(jù)取出來,在這種條件下,效率就會比全表掃描的效率要差一些。emp表比較大時,而且deptno=10條件能查詢出表中大部分的數(shù)據(jù)如(50%)。如該表共有4000萬行數(shù)據(jù),共放在有500000個數(shù)據(jù)塊中,每個數(shù)據(jù)塊為8k,則該表共有約4G則這么多的

31、數(shù)據(jù)不可能全放在內(nèi)存中,絕大多數(shù)需要放在硬盤上。此時如果該查詢通過索引查詢,則是你夢魘的開始。db_file_multiblock_read_count參數(shù)的值200。如果采用全表掃描,則需要500000/db_file_multiblock_read_count=500000/200=2500次I/O。但是如果采用索引掃描,假設(shè)deptno列上的索引都已經(jīng)cache到內(nèi)存中,所以可以將訪問索引的開銷忽略不計。因為要讀出4000萬x50%=2000萬數(shù)據(jù),假設(shè)在讀這2000萬數(shù)據(jù)時,有99.9%的命中率,則還是需要20000次I/O,比上面的全表掃描需要的2500次多多了,所以在這種情況下,用

32、索引掃描反而性能會差很多。在這樣的情況下,用全表掃描的時間是固定的,但是用索引掃描的時間會隨著選出數(shù)據(jù)的增多使查詢時間相應(yīng)的延長。上面是枯燥的假設(shè)數(shù)據(jù),現(xiàn)在以具體的實例給予驗證:環(huán)境:oracle817+linux+陣列柜,表SWD_BILLDETAI有3200多萬數(shù)據(jù);表的id列、cn列上都有索引經(jīng)查看執(zhí)行計劃,發(fā)現(xiàn)執(zhí)行selectcount(id)fromSWD_BILLDETAIL;使用全表掃描,執(zhí)行完用了大約1.50分鐘(4次執(zhí)行取平均,每次分別為1.451.512.001.46)。而執(zhí)行selectcount(id)fromSWD_BILLDETAILwherecn6;卻用了2個小時

33、還沒有執(zhí)行完,經(jīng)分析該語句使用了cn列上的索引,然后利用查詢出的rowid再從表中查詢數(shù)據(jù)。我為什么不使用selectcount(cn)fromSWD_BILLDETAILwherecn1對于需要訪問跨節(jié)點(即通常說的服務(wù)器)數(shù)據(jù)庫上數(shù)據(jù)的查詢來說,存在network代價,用來量化傳輸操作耗費的資源。查詢遠(yuǎn)程表的查詢或執(zhí)行分布式連接的查詢會在network代價方面花費比較大。在使用CBO寸,需要有表和索引的統(tǒng)計數(shù)據(jù)(分析數(shù)據(jù))作為基礎(chǔ)數(shù)據(jù),有了這些數(shù)據(jù),CBO才能為各個執(zhí)行計劃計算出相對準(zhǔn)確的代價,從而使CBO選擇最佳的執(zhí)行計劃。所以定期的對表、索引進(jìn)行分析是絕對必要的,這樣才能使統(tǒng)計數(shù)據(jù)反映

34、數(shù)據(jù)庫中的真實情況。否則就會使CBO選擇較差的執(zhí)行計劃,影響數(shù)據(jù)庫的性能。分析操作不必做的太頻繁,一般來說,每星期一次就足夠了。切記如果想使用CBQ則必須定期對表和索引進(jìn)行分析。對于分析用的命令,隨著數(shù)據(jù)庫版本的升級,用的命令也發(fā)生了變換,在oracle&以前,主要是用ANALYZ命令。在QRACLEI以后,又引入了DBMS_STATS存儲包來進(jìn)行分析。幸運的是從ORACLE10(以后,分析工作變成自動的了,這減輕的DBA的負(fù)擔(dān),不過在一些特殊情況下,還需要一些手工分析。如果采用了CBQ優(yōu)化器,而沒有對表和索引進(jìn)行分析,沒有統(tǒng)計數(shù)據(jù),則QRACL使用缺省的統(tǒng)計數(shù)據(jù)(至少在QRACLEI中是這樣

35、),這可以從oracle的文檔上找到。使用的缺省值肯定和系統(tǒng)的實際統(tǒng)計值不一致,這可能會導(dǎo)致優(yōu)化器選擇錯誤的執(zhí)行計劃,影響數(shù)據(jù)庫的性能。要注意的是:雖然CBC的功能隨著QRACL新版本的推出,功能越來越強,但它不是能包治百病的神藥,否則就不再需要DBA了,那我就慘了!實際上任何一個語句,隨著硬件環(huán)境和使用數(shù)據(jù)的不同,該語句的執(zhí)行計劃可能需要隨之發(fā)生變化,這樣才能取得最好的性能。所以有時候不在具體的環(huán)境下而進(jìn)行SQL性能調(diào)整是徒勞的。在QRACLE8推出的時候,QRACL極力建議大家使用CBQ說CBQt種種好處,但是在那是QRACL開發(fā)的使用系統(tǒng)還是使用基于規(guī)則的優(yōu)化器,從這件事上我們可以得出這

36、樣的結(jié)論:1)如果團隊的數(shù)據(jù)庫水平很高而且都熟悉使用數(shù)據(jù)的特點,RBQ也可以取得很好的性能。2)CBC不是很穩(wěn)定,但是一個比較有前途的優(yōu)化器,Oracle極力建議大家用是為了讓大家盡快發(fā)現(xiàn)它的BUG以便進(jìn)一步改善,但是QRACL為了對自己開發(fā)的使用系統(tǒng)負(fù)責(zé),他們還是使用了比較熟悉而且成熟的RBQ從這個事情上給我們的啟發(fā)就是:我們在以后的開發(fā)中,應(yīng)該盡量采用我們熟悉并且成熟的技術(shù),而不要一味的采用新技術(shù),一味采用新技術(shù)并不一定能開發(fā)出好的產(chǎn)品。幸運的是從ORACLE10(后,CBQ已經(jīng)足夠的強大和智能,大家可以放心的使用該技術(shù),因為QRACLE0G后,Qracle自己開發(fā)的使用系統(tǒng)也使用CBQ化

37、器了。而且QRACL規(guī)定,從QRACLE0G開始,開始廢棄RBQ化器。這句話并不是指在QRACL10G中不能使用RBQ而是從QRACLE0G開始開始,不再為RBQ的BUG提供修補服務(wù)。在上面的第2個例子中,如果采用CBQ優(yōu)化器,它就會考慮emp表的行數(shù),deptno列的統(tǒng)計數(shù)據(jù),發(fā)現(xiàn)對該列做查詢會查詢出過多的數(shù)據(jù),并且考慮db_file_multiblock_read_count參數(shù)的設(shè)置,發(fā)現(xiàn)用全表掃描的代價比用索引掃描的代價要小,從而使用全表掃描從而取得良好的執(zhí)行性能。判斷當(dāng)前數(shù)據(jù)庫使用何種優(yōu)化器:主要是由optimizer_mode初始化參數(shù)決定的。該參數(shù)可能的取值為:first_row

38、s_1|10|100|1000|first_rows|all_rows|choose|rule。具體解釋如下:RULE為使用RBO優(yōu)化器。CHOOSER是根據(jù)實際情況,如果數(shù)據(jù)字典中包含被引用的表的統(tǒng)計數(shù)據(jù),即引用的對象已經(jīng)被分析,則就使用CBO優(yōu)化器,否則為RBO優(yōu)化器。ALL_ROW為CBOffi化器使用的第一種具體的優(yōu)化方法,是以數(shù)據(jù)的吞吐量為主要目標(biāo),以便可以使用最少的資源完成語句。FIRST_ROW為優(yōu)化器使用的第二種具體的優(yōu)化方法,是以數(shù)據(jù)的響應(yīng)時間為主要目標(biāo),以便快速查詢出開始的幾行數(shù)據(jù)。FIRST_ROWS_1|10|100|1000為優(yōu)化器使用的第三種具體的優(yōu)化方法,讓優(yōu)化器

39、選擇一個能夠把響應(yīng)時間減到最小的查詢執(zhí)行計劃,以迅速產(chǎn)生查詢結(jié)果的前n行。該參數(shù)為ORACLE91新引入的。從ORACLEV以來,optimizer_mode參數(shù)的缺省設(shè)置應(yīng)是choose,即如果對已分析的表查詢的話選擇CBQ否則選擇RBO在此種設(shè)置中,如果采用了CBO則缺省為CBC中的all_rows模式。注意:即使指定數(shù)據(jù)庫使用RBO優(yōu)化器,但有時ORACL數(shù)據(jù)庫還是會采用CBO優(yōu)化器,這并不是ORACL的BUG主要是由于從ORACLEI后引入的許多新特性都必須在CBO下才能使用,而你的SQL語句可能正好使用了這些新特性,此時數(shù)據(jù)庫會自動轉(zhuǎn)為使用CBO優(yōu)化器執(zhí)行這些語句。什么是優(yōu)化優(yōu)化是選

40、擇最有效的執(zhí)行計劃來執(zhí)行SQL語句的過程,這是在處理任何數(shù)據(jù)的語句(SELECT,INSERT,UPDATEDELETE中的一個重要步驟。對Oracle來說,執(zhí)行這樣的語句有許多不同的方法,譬如說,將隨著以什么順序訪問哪些表或索引的不同而不同。所使用的執(zhí)行計劃可以決定語句能執(zhí)行得有多快。Oracle中稱之為優(yōu)化器(Optimizer)的組件用來選擇這種它認(rèn)為最有效的執(zhí)行計劃。由于一系列因素都會會影響語句的執(zhí)行,優(yōu)化器綜合權(quán)衡各個因素,在眾多的執(zhí)行計劃中選擇認(rèn)為是最佳的執(zhí)行計劃。然而,使用設(shè)計人員通常比優(yōu)化器更知道關(guān)于特定使用的數(shù)據(jù)特點。無論優(yōu)化器多么智能,在某些情況下開發(fā)人員能選擇出比優(yōu)化器選

41、擇的最優(yōu)執(zhí)行計劃還要好的執(zhí)行計劃。這是需要人工干預(yù)數(shù)據(jù)庫優(yōu)化的主要原因。事實表明,在某些情況下,確實需要DBA對某些語句進(jìn)行手工優(yōu)化。注:從Oracle的一個版本到另一個版本,優(yōu)化器可能對同一語句生成不同的執(zhí)行計劃。在將來的Oracle版本中,優(yōu)化器可能會基于它可以用的更好、更理想的信息,作出更優(yōu)的決策,從而導(dǎo)致為語句產(chǎn)生更優(yōu)的執(zhí)行計劃。第5章ORACLED執(zhí)行計劃背景知識:為了更好的進(jìn)行下面的內(nèi)容我們必須了解一些概念性的術(shù)語:共享sql語句為了不重復(fù)分析相同的SQL語句(因為分析操作比較費資源,會導(dǎo)致性能下降),在第一次分析之后,ORACL將SQL語句及分析后得到的執(zhí)行計劃存放在內(nèi)存中。這塊

42、位于系統(tǒng)全局區(qū)域SGA(systemglobalarea)的共享池(sharedbufferpool)中的內(nèi)存可以被所有的數(shù)據(jù)庫用戶共享。因此,當(dāng)你執(zhí)行一個SQL語句(有時被稱為一個游標(biāo))時,如果該語句和之前的執(zhí)行過的某一語句完全相同,并且之前執(zhí)行的該語句和其執(zhí)行計劃仍然在內(nèi)存中存在,則ORACL就不需要再進(jìn)行分析,直接得到該語句的執(zhí)行路徑。ORACL的這個功能大大地提高了SQL的執(zhí)行性能并大大節(jié)省了內(nèi)存的使用。使用這個功能的關(guān)鍵是將執(zhí)行過的語句盡可能放到內(nèi)存中,所以這要求有大的共享池(通過設(shè)置sharedbufferpool參數(shù)值)和盡可能的使用綁定變量的方法執(zhí)行SQL語句。當(dāng)你向ORACL

43、E!交一個SQL語句,ORACL會首先在共享內(nèi)存中查找是否有相同的語句。這里需要注明的是,ORACL對兩者采取的是一種嚴(yán)格匹配,要達(dá)成共享,SQL語句必須完全相同(包括空格,換行等)。下面是判斷SQL語句是否和共享內(nèi)存中某一SQL相同的步驟:1)對所發(fā)出語句的文本串進(jìn)行hashed。如果hash值和已在共享池中SQL語句的hash值相同,則進(jìn)行第2步;2)將所發(fā)出語句的文本串(包括大小寫、空白和注釋)和在第1步中識別的所有已存在的SQL語句相比較。例如:SELECT*FROMempWHEREempno=1000;和下列每一個都不同SELECT*fromempWHEREempno=1000;SE

44、LECT*FROMEMPWHEREempno=1000;SELECT*FROMempWHEREempno=2000;在上面的語句中列值都是直接SQL語句中的,今后我們將這類sql成為硬編碼SQL或字面值SQL使用綁定變量的SQL語句中必須使用相同的名字的綁定變量(bindvariables),例如:a.該2個sql語句被認(rèn)為相同selectpin,namefrompeoplewherepin=:blk1.pin;selectpin,namefrompeoplewherepin=:blk1.pin;b.該2個sql語句被認(rèn)為不相同selectpin,namefrompeoplewherepin=

45、:blk1.ot_ind;selectpin,namefrompeoplewherepin=:blk1.ov_ind;今后我們將上面的這類語句稱為綁定變量SQL。3)將所發(fā)出語句中涉及的對象和第2步中識別的已存在語句所涉及對象相比較。例如:如用戶userl和用戶user2下都有EMP表,則用戶userl發(fā)出的語句:SELECT*FROMEMP;和用戶user2發(fā)出的語句:SELECT*FROMEMP被認(rèn)為是不相同的語句,因為兩個語句中引用的EMP不是指同一個表。4)在SQL語句中使用的捆綁變量的捆綁類型必須一致。如果語句和當(dāng)前在共享池中的另一個語句是等同的話,Oracle并不對它進(jìn)行語法分析。

46、而直接執(zhí)行該語句,提高了執(zhí)行效率,因為語法分析比較耗費資源。注意的是,從oracle8i開始,新引入了一個CURSOR_SHAR參數(shù),該參數(shù)的主要目的就是為了解決在編程過程中已大量使用的硬編碼SQL問題。因為在實際開發(fā)中,很多程序人員為了提高開發(fā)速度,而采用類似下面的開發(fā)方法:str_sqlstring;int_empnoint;int_empno=2000;str_sql=SELECT*FROMempWHEREempno=+int_empno;int_empno=1000;str_sql=SELECT*FROMempWHEREempno=+int_empno;上面的代碼實際上使用了硬編碼SQ

47、L使我們不能使用共享SQL的功能,結(jié)果是數(shù)據(jù)庫效率不高。但是從上面的2個語句來看,產(chǎn)生的硬編碼SQL只是列值不同,其它部分都是相同的,如果僅僅因為列值不同而導(dǎo)致這2個語句不能共享是很可惜的,為了解決這個問題,弓I入了CURSOR_SHARI參數(shù),使這類問題也可以使用共享SQL從而使這樣的開發(fā)也可以利用共享SQL功能。聽起來不錯,ORACL真為用戶著想,使用戶在不改變代碼的情況下還可以利用共享SQL的功能。真的如此嗎?天上不會無緣無故的掉一個餡餅的,ORACL對該參數(shù)的使用做了說明,建議在經(jīng)過實際測試后再改該參數(shù)的值(缺省情況下,該參數(shù)的值為EXACT語句完全一致才使用共享SQL)。因為有可能該

48、變該值后,你的硬編碼SQL是可以使用共享SQL了,但數(shù)據(jù)庫的性能反而會下降。我在實際使用中已經(jīng)遇到這種情況。所以建議編寫需要穩(wěn)定運行程序的開發(fā)人員最好還是一開始就使用綁定變量的SQL。Rowid的概念:rowid是一個偽列,既然是偽列,那么這個列就不是用戶定義,而是系統(tǒng)自己給加上的。對每個表都有一個rowid的偽列,但是表中并不物理存儲ROWID列的值。不過你可以像使用其它列那樣使用它,但是不能刪除改列,也不能對該列的值進(jìn)行修改、插入。一旦一行數(shù)據(jù)插入數(shù)據(jù)庫,則rowid在該行的生命周期內(nèi)是唯一的,即即使該行產(chǎn)生行遷移,行的rowid也不會改變。為什么使用ROWIDrowid對訪問一個表中的給

49、定的行提供了最快的訪問方法,通過ROWI可以直接定位到相應(yīng)的數(shù)據(jù)塊上,然后將其讀到內(nèi)存。我們創(chuàng)建一個索引時,該索引不但存儲索引列的值,而且也存儲索引值所對應(yīng)的行的ROWID這樣我們通過索引快速找到相應(yīng)行的ROWID后,通過該ROWID就可以迅速將數(shù)據(jù)查詢出來。這也就是我們使用索引查詢時,速度比較快的原因。在ORACLE以前的版本中,ROWI由FILE、BLOCKROWNUMBE成。隨著oracle8中對象概念的擴展,ROWI發(fā)生了變化,ROWI由OBJECTFILE、BLOCKROVNUMBE構(gòu)成。利用DBMS_ROWID以將rowid分解成上述的各部分,也可以將上述的各部分組成一個有效的ro

50、wid。RecursiveSQL概念有時為了執(zhí)行用戶發(fā)出的一個sql語句,Oracle必須執(zhí)行一些額外的語句,我們將這些額外的語句稱之為recursivecalls或recursiveSQLstatements。如當(dāng)一個DDL語句發(fā)出后,ORACLED是隱含的發(fā)出一些recursiveSQL語句,來修改數(shù)據(jù)字典信息,以便用戶可以成功的執(zhí)行該DDL語句。當(dāng)需要的數(shù)據(jù)字典信息沒有在共享內(nèi)存中時,經(jīng)常會發(fā)生Recursivecalls,這些Recursivecalls會將數(shù)據(jù)字典信息從硬盤讀入內(nèi)存中。用戶不比關(guān)心這些recursiveSQL語句的執(zhí)行情況,在需要的時候,ORACLED自動的在內(nèi)部執(zhí)行

51、這些語句。當(dāng)然DML語句和SELEC嘟可能引起recursiveSQL。簡單的說,我們可以將觸發(fā)器視為recursiveSQL。RowSource(行源)用在查詢中,由上一操作返回的符合條件的行的集合,即可以是表的全部行數(shù)據(jù)的集合;也可以是表的部分行數(shù)據(jù)的集合;也可以為對上2個rowsource進(jìn)行連接操作(如join連接)后得到的行數(shù)據(jù)集合。Predicate(謂詞)一個查詢中的WHERE制條件DrivingTable(驅(qū)動表)該表又稱為外層表(OUTERTABLE)這個概念用于嵌套和HASH連接中。如果該rowsource返回較多的行數(shù)據(jù),則對所有的后續(xù)操作有負(fù)面影響。注意此處雖然翻譯為驅(qū)

52、動表,但實際上翻譯為驅(qū)動行源(drivingrowsource)更為確切。一般說來,是使用查詢的限制條件后,返回較少行源的表作為驅(qū)動表,所以如果一個大表在WHER條件有有限制條件(如等值限制),則該大表作為驅(qū)動表也是合適的,所以并不是只有較小的表可以作為驅(qū)動表,正確說法應(yīng)該為使用查詢的限制條件后,返回較少行源的表作為驅(qū)動表。在執(zhí)行計劃中,應(yīng)該為靠上的那個rowsource,后面會給出具體說明。在我們后面的描述中,一般將該表稱為連接操作的rowsource1。ProbedTable(被探查表)該表又稱為內(nèi)層表(INNERTABLE。在我們從驅(qū)動表中得到具體一行的數(shù)據(jù)后,在該表中尋找符合連接條件的

53、行。所以該表應(yīng)當(dāng)為大表(實際上應(yīng)該為返回較大rowsource的表)且相應(yīng)的列上應(yīng)該有索引。在我們后面的描述中,一般將該表稱為連接操作的rowsource2。組合索引(concatenatedindex)由多個列構(gòu)成的索引,如createindexidx_emp1INDEXUNIQUESCANEMP_I1進(jìn)一步講,如果sql語句中對索引列進(jìn)行排序,因為索引已經(jīng)預(yù)先排序好了,所以在執(zhí)行計劃中不需要再對索引列進(jìn)行排序SQLexplainplanforselectempno,enamefromempwhereempno7876orderbyempno;QueryPlanSELECTSTATEMENT

54、CHOOSECost=1TABLEACCESSBYROWIDEMPANALYZEDINDEXRANGESCANEMP_I1ANALYZED從這個例子中可以看到:因為索引是已經(jīng)排序了的,所以將按照索引的順序查詢出符合條件的行,因此避免了進(jìn)一步排序操作。根據(jù)索引的類型和where限制條件的不同,有4種類型的索引掃描:索引唯一掃描(indexuniquescan)索引范圍掃描(indexrangescan)索引全掃描(indexfullscan)索引快速掃描(indexfastfullscan)(1)索引唯一掃描(indexuniquescan)通過唯一索引查找一個數(shù)值經(jīng)常返回單個ROWID如果該唯

55、一索引有多個列組成(即組合索引),則至少要有組合索引的引導(dǎo)列參和到該查詢中,如創(chuàng)建一個索引:createindexidx_test1RowSource1RowSource2如果rowsource已經(jīng)在連接關(guān)聯(lián)列上被排序,則該連接操作就不需要再進(jìn)行sort操作,這樣可以大大提高這種連接操作的連接速度,因為排序是個極其費資源的操作,特別是對于較大的表。預(yù)先排序的rowsource包括已經(jīng)被索引的列(如a.col3或b.col4上有索引)或rowsource已經(jīng)在前面的步驟中被排序了。盡管合并兩個rowsource的過程是串行的,但是可以并行訪問這兩個rowsource(如并行讀入數(shù)據(jù),并行排序).

56、SMJ連接的例子:SQLexplainplanforselect/*+ordered*/e.deptno,d.deptnofromempe,deptdwheree.deptno=d.deptnoorderbye.deptno,d.deptno;QueryPlanSELECTSTATEMENTCHOOSECost=17MERGEJOINSORTJOINTABLEACCESSFULLEMPANALYZEDSORTJOINTABLEACCESSFULLDEPTANALYZED排序是一個費時、費資源的操作,特別對于大表。基于這個原因,SMJ經(jīng)常不是一個特別有效的連接方法,但是如果2個rowsource

57、都已經(jīng)預(yù)先排序,則這種連接方法的效率也是蠻高的。嵌套循環(huán)(NestedLoops,NL)這個連接方法有驅(qū)動表(外部表)的概念。其實,該連接過程就是一個2層嵌套循環(huán),所以外層循環(huán)的次數(shù)越少越好,這也就是我們?yōu)槭裁磳⑿”砘蚍祷剌^小rowsource的表作為驅(qū)動表(用于外層循環(huán))的理論依據(jù)。但是這個理論只是一般指導(dǎo)原則,因為遵循這個理論并不能總保證使語句產(chǎn)生的I/O次數(shù)最少。有時不遵守這個理論依據(jù),反而會獲得更好的效率。如果使用這種方法,決定使用哪個表作為驅(qū)動表很重要。有時如果驅(qū)動表選擇不正確,將會導(dǎo)致語句的性能很差、很差。內(nèi)部連接過程:Rowsource1的Row1Rowsource1的Row2R

58、owsource1的Row3Probe-Rowsource2Probe-Rowsource2Probe-Rowsource2Rowsource1的RownRowsource1的RownProbe-Rowsource2從內(nèi)部連接過程來看,需要用rowsource1中的每一行,去匹配rowsource2中的所有行,所以此時保持rowsource1盡可能的小和高效的訪問rowsource2(一般通過索引實現(xiàn))是影響這個連接效率的關(guān)鍵問題。這只是理論指導(dǎo)原則,目的是使整個連接操作產(chǎn)生最少的物理I/O次數(shù),而且如果遵守這個原則,一般也會使總的物理I/O數(shù)最少。但是如果不遵從這個指導(dǎo)原則,反而能用更少的物

59、理I/O實現(xiàn)連接操作,那盡管違反指導(dǎo)原則吧!因為最少的物理I/O次數(shù)才是我們應(yīng)該遵從的真正的指導(dǎo)原。在上面的連接過程中,我們稱Rowsource1為驅(qū)動表或外部表。RowSource2被稱為被探查表或內(nèi)部表。在NESTEDLOOP連接中,Oracle讀取rowsourcel中的每一行,然后在rowsourc2中檢查是否有匹配的行,所有被匹配的行都被放到結(jié)果集中,然后處理rowsource1中的下一行。這個過程一直繼續(xù),直到rowsource1中的所有行都被處理。這是從連接操作中可以得到第一個匹配行的最快的方法之一,這種類型的連接可以用在需要快速響應(yīng)的語句中,以響應(yīng)速度為主要目標(biāo)。如果drivi

60、ngrowsource(外部表)比較小,并且在innerrowsource(內(nèi)部表)上有唯一索引,或有高選擇性非唯一索引時,使用這種方法可以得到較好的效率。NESTEDLOOPS其它連接方法沒有的的一個優(yōu)點是:可以先返回已經(jīng)連接的行,而不必等待所有的連接操作處理完才返回數(shù)據(jù),這可以實現(xiàn)快速的響應(yīng)時間。如果不使用并行操作,最好的驅(qū)動表是那些使用了where限制條件后,可以返回較少行數(shù)據(jù)的的表,所以大表也可能稱為驅(qū)動表,關(guān)鍵看限制條件。對于并行查詢,我們經(jīng)常選擇大表作為驅(qū)動表,因為大表可以充分利用并行功能。當(dāng)然,有時對查詢使用并行操作并不一定會比查詢不使用并行操作效率高,因為最后可能每個表只有很少

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論