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

下載本文檔

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

文檔簡介

通過分析SQL語句的執(zhí)行計劃優(yōu)化SQL第1章 性能調(diào)整綜述第2章 有效的應(yīng)用設(shè)計第3章SQL語句處理的過程第4章 ORACLE的優(yōu)化器第5章 ORACLE的執(zhí)行計劃 訪問路徑(方法) - access path 表之間的連接 如何產(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),若干類人員必須交換信息并牽涉到系統(tǒng)調(diào)整中,例如: 應(yīng)用設(shè)計人員必須傳達(dá)應(yīng)用系統(tǒng)的設(shè)計,使得每個人都清楚應(yīng)用中的數(shù)據(jù)流動. 應(yīng)用開發(fā)人員必須傳達(dá)他們選擇的實(shí)現(xiàn)策略,使得語句調(diào)整的過程中能快速、容易地識別有問題的應(yīng)用模塊和可疑的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)整就能相對的容易和更快一些。 不幸的是,事實(shí)上的結(jié)果是:數(shù)據(jù)庫管理員對調(diào)整負(fù)有全部或主要的責(zé)任。但是,數(shù)據(jù)庫管理員很少有合適的系統(tǒng)方面的資料,而且,在很多情況下,數(shù)據(jù)庫管理 員往往是在實(shí)施階段才介入數(shù)據(jù)庫,這就給調(diào)整工作帶來許多負(fù)面的影響,因?yàn)樵谠O(shè)計階段的缺陷是不能通過DBA的調(diào)整而得以解決,而設(shè)計階段的缺陷往往對數(shù) 據(jù)庫性能造成極大的影響。 其實(shí),在真正成熟的開發(fā)環(huán)境下,開發(fā)人員作為純代碼編寫人員時,對性能的影響最小,此時大部分的工作應(yīng) 由應(yīng)用設(shè)計人員完成,而且數(shù)據(jù)庫管理員往往在前期的需求管理階段就介入,為設(shè)計人員提供必要的技術(shù)支持。調(diào)整并不是數(shù)據(jù)庫管理員的專利,相反大部分應(yīng)該是 設(shè)計人員和開發(fā)人員的工作,這就需要設(shè)計人員和開發(fā)人員具體必要的數(shù)據(jù)庫知識,這樣才能組成一個高效的團(tuán)隊,然而事實(shí)上往往并非如此。 什么時候作調(diào)整? 多數(shù)人認(rèn)為當(dāng)用戶感覺性能差時才進(jìn)行調(diào)整,這對調(diào)整過程中使用某些最有效的調(diào)整策略來說往往是太遲了。此時,如果你不愿意重新設(shè)計應(yīng)用的話,你只能通過 重新分配內(nèi)存(調(diào)整SGA)和調(diào)整I/O的辦法或多或少地提高性能。Oracle提供了許多特性,這些特性只有應(yīng)用到正確地設(shè)計的系統(tǒng)中時才能夠很大地提 高性能。 應(yīng)用設(shè)計人員需要在設(shè)計階段設(shè)置應(yīng)用的性能期望值。然后在設(shè)計和開發(fā)期間,應(yīng)用設(shè)計人員應(yīng)考慮哪些Oracle 特性可以對系統(tǒng)有好處,并使用這些特性。通過良好的系統(tǒng)設(shè)計,你就可以在應(yīng)用的生命周期中消除性能調(diào)整的代價和挫折。當(dāng)然,即使在設(shè)計很好的系統(tǒng)中,也可 能有性能降低。但這些性能降低應(yīng)該是可控的和可以預(yù)見的。 調(diào)整目標(biāo) 不管你正在設(shè)計或維護(hù)系統(tǒng),你應(yīng)該建立專門的性能目標(biāo),它使你知道何時要作調(diào)整。如果你試圖胡亂地改動初始化參數(shù)或SQl語句,你可能會浪費(fèi)調(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)時間小于秒。當(dāng)應(yīng)用不能滿足此目標(biāo)時,識別造成變慢的瓶頸(例如,I/O競爭),確定原因,采取糾正動作。在開發(fā)期間,你應(yīng)測試應(yīng)用研究,確定在采取應(yīng)用之前是否滿足設(shè)計的性能目標(biāo)。 當(dāng)你正在維護(hù)生產(chǎn)庫系統(tǒng)時,有多種快速有效的方法來識別性能瓶頸。不管怎樣,調(diào)整通常是一系列開銷。一旦你已確定了瓶頸,你可能要犧牲一些其它方面的指 標(biāo)來達(dá)到所要的結(jié)果。例如,如果I/O有問題,你可能需要更多內(nèi)存或磁盤。如果不可能買,你可能要限制系統(tǒng)的并發(fā)性,來獲取所需的性能。然而,如果你已經(jīng) 明確地定義了性能的目標(biāo),那用什么來交換高性能的決策就變的很容易的,因?yàn)槟阋呀?jīng)確定了哪些方面是最重要的,如過我的目標(biāo)為高性能,可能犧牲一些空間資 源。 隨著應(yīng)用的越來越龐大,硬件性能的提高,全面的調(diào)整應(yīng)用逐漸變成代價高昂的行為,在這樣情況下,要取得最大的投入/效率之 比,較好的辦法是調(diào)整應(yīng)用的關(guān)鍵部分,使其達(dá)到比較高的性能,這樣從總體上來說,整個系統(tǒng)的性能也是比較高的。這也就是有名的20/80原則,調(diào)整應(yīng)用的 20%(關(guān)鍵部分),能解決80%的問題。 在設(shè)計和開發(fā)系統(tǒng)時作調(diào)整 良好設(shè)計的系統(tǒng)可以防止在應(yīng)用生命周期中產(chǎn)生性能問題。系統(tǒng)設(shè)計人員和應(yīng)用開發(fā)人員必須了解Oracle的查詢處理機(jī)制以便寫出高效的SQl語句。“第2 章 有效的應(yīng)用設(shè)計”討論了你的系統(tǒng)中各種可用的配置,以及每種配置更適合哪種類型的應(yīng)用。“第4章 優(yōu)化器”討論了Oracle的查詢優(yōu)化器,以及如何寫語句以獲取最快的結(jié)果。 當(dāng)設(shè)計你的系統(tǒng)時,使用下列優(yōu)化性能的準(zhǔn)則: 消除客戶機(jī)服務(wù)器應(yīng)用中不必要的網(wǎng)絡(luò)傳輸。- 使用存儲過程。 使用適合你系統(tǒng)的相應(yīng)Oracle服務(wù)器選件(例如,并行查詢或分布式數(shù)據(jù)庫)。 除非你的應(yīng)用有特殊的需要,否則使用缺省的Oracle鎖。 利用數(shù)據(jù)庫記住應(yīng)用模塊,以便你能以每個模塊為基礎(chǔ)來追蹤性能。 選擇你的數(shù)據(jù)塊的最佳大小。 - 原則上來說大一些的性能較好。 分布你的數(shù)據(jù),使得一個節(jié)點(diǎn)使用的數(shù)據(jù)本地存貯在該節(jié)點(diǎn)中。 調(diào)整產(chǎn)品系統(tǒng) 本節(jié)描述對應(yīng)用系統(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_WAIT視圖,識別性能的瓶頸,這個動態(tài)性能視圖列出了造成會話(session)等待的事件。 通過分析V $SESSION_WAIT中的數(shù)據(jù),決定瓶頸的原因。 糾正存在的問題。 監(jiān)控應(yīng)用系統(tǒng) 這主要是通過監(jiān)控oracle的動態(tài)視圖來完成。各種有用的動態(tài)視圖:如v$session_wait, v$session_event等。 第2章 有效的應(yīng)用設(shè)計 我們通常將最常用的應(yīng)用分為2種類型:聯(lián)機(jī)事務(wù)處理類型(OLTP),決策支持系統(tǒng)(DSS)。 聯(lián)機(jī)事務(wù)處理(OLTP) 該類型的應(yīng)用是高吞吐量,插入、更新、刪除操作比較多的系統(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ā)用戶不能干擾系統(tǒng)的 性能。還需要避免使用過量的索引與cluster 表,因?yàn)檫@些結(jié)構(gòu)會使插入和更新操作變慢。 決策支持(DSS) 該類型的應(yīng)用將大量信息進(jìn)行提取形成報告,協(xié)助決策者作出正確的判斷。典型的情況是:決策支持系統(tǒng)將OLTP應(yīng)用收集的大量數(shù)據(jù)進(jìn)行查詢。典型的應(yīng)用為 客戶行為分析系統(tǒng)(超市,保險等)。決策支持的關(guān)鍵目標(biāo)是速度、精確性和可用性。該種類型的設(shè)計往往與OLTP設(shè)計的理念背道而馳,一般建議使用數(shù)據(jù)冗 余、大量索引、cluster table、并行查詢等。近年來,該類型的應(yīng)用逐漸與OLAP、數(shù)據(jù)倉庫緊密的聯(lián)系在一起,形成的一個新的應(yīng)用方向。第3章 SQL語句處理的過程 在調(diào)整之前我們需要了解一些背景知識,只有知道這些背景知識,我們才能更好的去調(diào)整sql語句。 本節(jié)介紹了SQL語句處理的基本過程,主要包括: 查詢語句處理 DML語句處理(insert, update, delete) DDL 語句處理(create . , drop . , alter . , ) 事務(wù)控制(commit, rollback) SQL 語句的執(zhí)行過程(SQL Statement Execution) 在某些情況下,Oracle運(yùn)行sql的過程可能與下面列出的各個階段的順序有所不同。如DEFINE階段可能在FETCH階段之前,這主要依賴你如何書寫代碼。 對許多oracle的工具來說,其中某些階段會自動執(zhí)行。絕大多數(shù)用戶不需要關(guān)心各個階段的細(xì)節(jié)問題,然而,知道執(zhí)行的各個階段還是有必要的,這會幫助 你寫出更高效的SQL語句來,而且還可以讓你猜測出性能差的SQL語句主要是由于哪一個階段造成的,然后我們針對這個具體的階段,找出解決的辦法。 DML語句的處理 本節(jié)給出一個例子來說明在DML語句處理的各個階段到底發(fā)生了什么事情。假設(shè)你使用Pro*C程序來為指定部門的所有職員增加工資。程序已經(jīng)連到正確的用戶,你可以在你的程序中嵌入如下的SQL語句: EXEC SQL UPDATE employees SET salary = 1.10 * salary WHERE department_id = :var_department_id; var_department_id是程序變量,里面包含部門號,我們要修改該部門的職員的工資。當(dāng)這個SQL語句執(zhí)行時,使用該變量的值。 每種類型的語句都需要如下階段: 第1步: Create a Cursor 創(chuàng)建游標(biāo) 第2步: Parse the Statement 分析語句 第5步: Bind Any Variables 綁定變量 第7步: Run the Statement 運(yùn)行語句 第9步: Close the Cursor 關(guān)閉游標(biāo) 如果使用了并行功能,還會包含下面這個階段: 第6步: Parallelize the Statement 并行執(zhí)行語句 如果是查詢語句,則需要以下幾個額外的步驟,如圖 3所示: 第3步: Describe Results of a Query 描述查詢的結(jié)果集 第4步: Define Output of a Query 定義查詢的輸出數(shù)據(jù) 第8步: Fetch Rows of a Query 取查詢出來的行 下面具體說一下每一步中都發(fā)生了什么事情:. 第1步: 創(chuàng)建游標(biāo)(Create a Cursor) 由程序接口調(diào)用創(chuàng)建一個游標(biāo)(cursor)。任何SQL語句都會創(chuàng)建它,特別在運(yùn)行DML語句時,都是自動創(chuàng)建游標(biāo)的,不需要開發(fā)人員干預(yù)。多數(shù)應(yīng)用 中,游標(biāo)的創(chuàng)建是自動的。然而,在預(yù)編譯程序(pro*c)中游標(biāo)的創(chuàng)建,可能是隱含的,也可能顯式的創(chuàng)建。在存儲過程中也是這樣的。 第2步:分析語句(Parse the Statement) 在語法分析期間,SQL語句從用戶進(jìn)程傳送到Oracle,SQL語句經(jīng)語法分析后,SQL語句本身與分析的信息都被裝入到共享SQL區(qū)。在該階段中,可以解決許多類型的錯誤。 語法分析分別執(zhí)行下列操作: 翻譯SQL語句,驗(yàn)證它是合法的語句,即書寫正確 實(shí)現(xiàn)數(shù)據(jù)字典的查找,以驗(yàn)證是否符合表和列的定義 在所要求的對象上獲取語法分析鎖,使得在語句的語法分析過程中不改變這些對象的定義 驗(yàn)證為存取所涉及的模式對象所需的權(quán)限是否滿足 決定此語句最佳的執(zhí)行計劃 將它裝入共享SQL區(qū) 對分布的語句來說,把語句的全部或部分路由到包含所涉及數(shù)據(jù)的遠(yuǎn)程節(jié)點(diǎn) 以上任何一步出現(xiàn)錯誤,都將導(dǎo)致語句報錯,中止執(zhí)行。 只有在共享池中不存在等價SQL語句的情況下,才對SQL語句作語法分析。在這種情況下,數(shù)據(jù)庫內(nèi)核重新為該語句分配新的共享SQL區(qū),并對語句進(jìn)行語法分析。進(jìn)行語法分析需要耗費(fèi)較多的資源,所以要盡量避免進(jìn)行語法分析,這是優(yōu)化的技巧之一。 語法分析階段包含了不管此語句將執(zhí)行多少次,而只需分析一次的處理要求。Oracle只對每個SQL語句翻譯一次,在以后再次執(zhí)行該語句時,只要該語句 還在共享SQL區(qū)中,就可以避免對該語句重新進(jìn)行語法分析,也就是此時可以直接使用其對應(yīng)的執(zhí)行計劃對數(shù)據(jù)進(jìn)行存取。這主要是通過綁定變量(bind variable)實(shí)現(xiàn)的,也就是我們常說的共享SQL,后面會給出共享SQL的概念。 雖然語法分析驗(yàn)證了SQL語句的正確性, 但語法分析只能識別在SQL語句執(zhí)行之前所能發(fā)現(xiàn)的錯誤(如書寫錯誤、權(quán)限不足等)。因此,有些錯誤通過語法分析是抓不到的。例如,在數(shù)據(jù)轉(zhuǎn)換中的錯誤或 在數(shù)據(jù)中的錯(如企圖在主鍵中插入重復(fù)的值)以及死鎖等均是只有在語句執(zhí)行階段期間才能遇到和報告的錯誤或情況。 查詢語句的處理 查詢與其它類型的SQL語句不同,因?yàn)樵诔晒?zhí)行后作為結(jié)果將返回數(shù)據(jù)。其它語句只是簡單地返回成功或失敗,而查詢則能返回一行或許多行數(shù)據(jù)。查詢的結(jié) 果均采用表格形式,結(jié)果行被一次一行或者批量地被檢索出來。從這里我們可以得知批量的fetch數(shù)據(jù)可以降低網(wǎng)絡(luò)開銷,所以批量的fetch也是優(yōu)化的技 巧之一。 有些問題只與查詢處理相關(guān),查詢不僅僅指SELECT語句,同樣也包括在其它SQL語句中的隱含查詢。例如,下面的每個語句都需要把查詢作為它執(zhí)行的一部分: INSERT INTO table SELECT. UPDATE table SET x = y WHERE. DELETE FROM table WHERE. CREATE table AS SELECT. 具體來說,查詢 要求讀一致性 可能使用回滾段作中間處理 可能要求SQL語句處理描述、定義和取數(shù)據(jù)階段 第3步: 描述查詢結(jié)果(Describe Results of a Query) 描述階段只有在查詢結(jié)果的各個列是未知時才需要;例如,當(dāng)查詢由用戶交互地輸入需要輸出的列名。在這種情況要用描述階段來決定查詢結(jié)果的特征(數(shù)據(jù)類型,長度和名字)。 第4步: 定義查詢的輸出數(shù)據(jù)(Define Output of a Query) 在查詢的定義階段,你指定與查詢出的列值對應(yīng)的接收變量的位置、大小和數(shù)據(jù)類型,這樣我們通過接收變量就可以得到查詢結(jié)果。如果必要的話,Oracle會自動實(shí)現(xiàn)數(shù)據(jù)類型的轉(zhuǎn)換。這是將接收變量的類型與對應(yīng)的列類型相比較決定的。 第5步: 綁定變量(Bind Any Variables) 此時,Oracle知道了SQL語句的意思,但仍沒有足夠的信息用于執(zhí)行該語句。Oracle 需要得到在語句中列出的所有變量的值。在該例中,Oracle需要得到對department_id列進(jìn)行限定的值。得到這個值的過程就叫綁定變量 (binding variables) 此過程稱之為將變量值捆綁進(jìn)來。程序必須指出可以找到該數(shù)值的變量名(該變量被稱為捆綁 變量,變量名實(shí)質(zhì)上是一個內(nèi)存地址,相當(dāng)于指針)。應(yīng)用的最終用戶可能并沒有發(fā)覺他們正在指定捆綁變量,因?yàn)镺racle 的程序可能只是簡單地指示他們輸入新的值,其實(shí)這一切都在程序中自動做了。因?yàn)槟阒付俗兞棵?,在你再次?zhí)行之前無須重新捆綁變量。你可以改變綁定變量的 值,而Oracle在每次執(zhí)行時,僅僅使用內(nèi)存地址來查找此值。如果Oracle 需要實(shí)現(xiàn)自動數(shù)據(jù)類型轉(zhuǎn)換的話(除非它們是隱含的或缺省的),你還必須對每個值指定數(shù)據(jù)類型和長度。關(guān)于這些信息可以參考o(jì)racle的相關(guān)文檔,如 Oracle Call Interface Programmers Guide 第6步: 并行執(zhí)行語句(Parallelize the Statement ) ORACLE 可以在SELECTs, INSERTs, UPDATEs, MERGEs, DELETEs語句中執(zhí)行相應(yīng)并行查詢操作,對于某些DDL操作,如創(chuàng)建索引、用子查詢創(chuàng)建表、在分區(qū)表上的操作,也可以執(zhí)行并行操作。并行化可以導(dǎo)致多 個服務(wù)器進(jìn)程(oracle server processes)為同一個SQL語句工作,使該SQL語句可以快速完成,但是會耗費(fèi)更多的資源,所以除非很有必要,否則不要使用并行查詢。 第7步: 執(zhí)行語句(Run the Statement) 到了現(xiàn)在這個時候,Oracle擁有所有需要的信息與資源,因此可以真正運(yùn)行SQL語句了。如果該語句為SELECT查詢或INSERT語句,則不需要 鎖定任何行,因?yàn)闆]有數(shù)據(jù)需要被改變。然而,如果語句為UPDATE或DELETE語句,則該語句影響的所有行都被鎖定,防止該用戶提交或回滾之前,別的 用戶對這些數(shù)據(jù)進(jìn)行修改。這保證了數(shù)據(jù)的一致性。對于某些語句,你可以指定執(zhí)行的次數(shù),這稱為批處理(array processing)。指定執(zhí)行N次,則綁定變量與定義變量被定義為大小為N的數(shù)組的開始位置,這種方法可以減少網(wǎng)絡(luò)開銷,也是優(yōu)化的技巧之一。 第8步: 取出查詢的行(Fetch Rows of a Query) 在fetch階段,行數(shù)據(jù)被取出來,每個后續(xù)的存取操作檢索結(jié)果集中的下一行數(shù)據(jù),直到最后一行被取出來。上面提到過,批量的fetch是優(yōu)化的技巧之一。 第9步: 關(guān)閉游標(biāo)(Close the Cursor) SQL語句處理的最后一個階段就是關(guān)閉游標(biāo) DDL語句的處理(DDL Statement Processing) DDL語句的執(zhí)行不同與DML語句和查詢語句的執(zhí)行,這是因?yàn)镈DL語句執(zhí)行成功后需要對數(shù)據(jù)字典數(shù)據(jù)進(jìn)行修改。對于DDL語句,語句的分析階段實(shí)際上 包括分析、查找數(shù)據(jù)字典信息和執(zhí)行。事務(wù)管理語句、會話管理語句、系統(tǒng)管理語句只有分析與執(zhí)行階段,為了重新執(zhí)行該語句,會重新分析與執(zhí)行該語句。 事務(wù)控制(Control of Transactions) 一般來說,只有使用ORACLE編程接口的應(yīng)用設(shè)計人員才關(guān)心操作的類型,并把相關(guān)的操作組織在一起,形成一個事務(wù)。一般來說,我門必須定義事務(wù),這樣 在一個邏輯單元中的所有工作可以同時被提交或回滾,保證了數(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)行一致更改(one consistent change to the data)的SQL語句 例如,在兩個帳號之間的轉(zhuǎn)帳(這是一個事務(wù)或邏輯工作單元),應(yīng)該包含從一個帳號中借錢(由一個SQL完成),然后將借的錢存入另一個帳號(由另一個 SQL完成)。這2個操作作為一個邏輯單元,應(yīng)該同時成功或同時失敗。其它不相關(guān)的操作,如向一個帳戶中存錢,不應(yīng)該包含在這個轉(zhuǎn)帳事務(wù)中。 在設(shè)計應(yīng)用時,除了需要決定哪種類型的操作組成一個事務(wù)外,還需要決定使用BEGIN_DISCRETE_TRANSACTIO存儲過程是否對提高小的、非分布式的事務(wù)的性能有作用。第4章 ORACLE的優(yōu)化器 優(yōu)化器有時也被稱為查詢優(yōu)化器,這是因?yàn)椴樵兪怯绊憯?shù)據(jù)庫性能 最主要的部分,不要以為只有SELECT語句是查詢。實(shí)際上,帶有任何WHERE條件的DML(INSERT、UPDATE、DELETE)語句中都包含 查詢要求,在后面的文章中,當(dāng)說到查詢時,不一定只是指SELECT語句,也有可能指DML語句中的查詢部分。優(yōu)化器是所有關(guān)系數(shù)據(jù)庫引擎中的最神秘、最 富挑戰(zhàn)性的部件之一,從性能的角度看也是最重要的部分,它性能的高低直接關(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)化器決定,而不是應(yīng)用開發(fā)者通過編程決定。在處理SQL的SELECT、UPDATE、INSERT或DELETE語句 時,Oracle 必須訪問語句所涉及的數(shù)據(jù),Oracle的優(yōu)化器部分用來決定訪問數(shù)據(jù)的有效路徑,使得語句執(zhí)行所需的I/O和處理時間最小。 為了實(shí)現(xiàn)一個查詢,內(nèi)核必須為每個查詢定制一個查詢策略,或?yàn)槿〕龇蠗l件的數(shù)據(jù)生成一個執(zhí)行計劃(execution plan)。典型的,對于同一個查詢,可能有幾個執(zhí)行計劃都符合要求,都能得到符合條件的數(shù)據(jù)。例如,參與連接的表可以有多種不同的連接方法,這取決于連 接條件和優(yōu)化器采用的連接方法。為了在多個執(zhí)行計劃中選擇最優(yōu)的執(zhí)行計劃,優(yōu)化器必須使用一些實(shí)際的指標(biāo)來衡量每個執(zhí)行計劃使用的資源(I/0次數(shù)、 CPU等),這些資源也就是我們所說的代價(cost)。如果一個執(zhí)行計劃使用的資源多,我們就說使用執(zhí)行計劃的代價大。以執(zhí)行計劃的代價大小作為衡量標(biāo) 準(zhǔn),優(yōu)化器選擇代價最小的執(zhí)行計劃作為真正執(zhí)行該查詢的執(zhí)行計劃,并拋棄其它的執(zhí)行計劃。 在ORACLE的發(fā)展過程中,一共開發(fā)過2種類型的優(yōu)化器:基于規(guī)則的優(yōu)化器和基于代價的優(yōu)化器。這2種優(yōu)化器的不同之處關(guān)鍵在于:取得代價的方法與衡量代價的大小不同?,F(xiàn)對每種優(yōu)化器做一下簡單的介紹: 基于規(guī)則的優(yōu)化器 - Rule Based (Heuristic) Optimization(簡稱RBO): 在ORACLE7之前,主要是使用基于規(guī)則的優(yōu)化器。ORACLE在基于規(guī)則的優(yōu)化器中采用啟發(fā)式的方法(Heuristic Approach)或規(guī)則(Rules)來生成執(zhí)行計劃。例如,如果一個查詢的where條件(where clause)包含一個謂詞(predicate,其實(shí)就是一個判斷條件,如”=”, “”, ”等),而且該謂詞上引用的列上有有效索引,那么優(yōu)化器將使用索引訪問這個表,而不考慮其它因素,如表中數(shù)據(jù)的多少、表中數(shù)據(jù)的易變性、索引的 可選擇性等。此時數(shù)據(jù)庫中沒有關(guān)于表與索引數(shù)據(jù)的統(tǒng)計性描述,如表中有多上行,每行的可選擇性等。優(yōu)化器也不考慮實(shí)例參數(shù),如multi block i/o、可用排序內(nèi)存的大小等,所以優(yōu)化器有時就選擇了次優(yōu)化的計劃作為真正的執(zhí)行計劃,導(dǎo)致系統(tǒng)性能不高。 如,對于 select * from emp where deptno = 10這個查詢來說,如果是使用基于規(guī)則的優(yōu)化器,而且deptno列上有有效的索引,則會通過deptno列上的索引來訪問emp表。在絕大多數(shù)情況下, 這是比較高效的,但是在一些特殊情況下,使用索引訪問也有比較低效的時候,現(xiàn)舉例說明: 1) emp表比較小,該表的數(shù)據(jù)只存放在幾個數(shù)據(jù)塊中。此時使用全表掃描比使用索引訪問emp表反而要好。因?yàn)楸肀容^小,極有可能數(shù)據(jù)全在內(nèi)存中,所以此時做 全表掃描是最快的。而如果使用索引掃描,需要先從索引中找到符合條件記錄的rowid,然后再一一根據(jù)這些rowid從emp中將數(shù)據(jù)取出來,在這種條件 下,效率就會比全表掃描的效率要差一些。 2) emp表比較大時,而且deptno = 10條件能查詢出表中大部分的數(shù)據(jù)如(50%)。如該表共有4000萬行數(shù)據(jù),共放在有500000個數(shù)據(jù)塊中,每個數(shù)據(jù)塊為8k,則該表共有約4G,則 這么多的數(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)存中,所以可以將訪問索引的開銷忽略不計。因?yàn)橐x出4000萬x 50% = 2000萬數(shù)據(jù),假設(shè)在讀這2000萬數(shù)據(jù)時,有99.9%的命中率,則還是需要20000次I/O,比上面的全表掃描需要的2500次多多了,所以在這 種情況下,用索引掃描反而性能會差很多。在這樣的情況下,用全表掃描的時間是固定的,但是用索引掃描的時間會隨著選出數(shù)據(jù)的增多使查詢時間相應(yīng)的延長。 上面是枯燥的假設(shè)數(shù)據(jù),現(xiàn)在以具體的實(shí)例給予驗(yàn)證: 環(huán)境: oracle 817 + linux + 陣列柜,表SWD_BILLDETAIL有3200多萬數(shù)據(jù); 表的id列、cn列上都有索引 經(jīng)查看執(zhí)行計劃,發(fā)現(xiàn)執(zhí)行select count(id) from SWD_BILLDETAIL;使用全表掃描,執(zhí)行完用了大約1.50分鐘(4次執(zhí)行取平均,每次分別為1.45 1.51 2.00 1.46)。而執(zhí)行select count(id) from SWD_BILLDETAIL where cn 6;卻用了2個小時還沒有執(zhí)行完,經(jīng)分析該語句使用了cn列上的索引,然后利用查詢出的rowid再從表中查詢數(shù)據(jù)。我為什么不使用 select count(cn) from SWD_BILLDETAIL where cn 1對于需要訪問跨節(jié)點(diǎn)(即通常說的服務(wù)器)數(shù)據(jù)庫上數(shù)據(jù)的查詢來說,存在network代價,用來量化傳輸操作耗費(fèi)的資源。查詢遠(yuǎn)程表的查詢或執(zhí)行分布式連接的查詢會在network代價方面花費(fèi)比較大。 在使用CBO時,需要有表和索引的統(tǒng)計數(shù)據(jù)(分析數(shù)據(jù))作為基礎(chǔ)數(shù)據(jù),有了這些數(shù)據(jù),CBO才能為各個執(zhí)行計劃計算出相對準(zhǔn)確的代價,從而使CBO選擇 最佳的執(zhí)行計劃。所以定期的對表、索引進(jìn)行分析是絕對必要的,這樣才能使統(tǒng)計數(shù)據(jù)反映數(shù)據(jù)庫中的真實(shí)情況。否則就會使CBO選擇較差的執(zhí)行計劃,影響數(shù)據(jù) 庫的性能。分析操作不必做的太頻繁,一般來說,每星期一次就足夠了。切記如果想使用CBO,則必須定期對表和索引進(jìn)行分析。 對于 分析用的命令,隨著數(shù)據(jù)庫版本的升級,用的命令也發(fā)生了變換,在oracle 8i以前,主要是用ANALYZE命令。在ORACLE 8I以后,又引入了DBMS_STATS存儲包來進(jìn)行分析。幸運(yùn)的是從ORACLE 10G以后,分析工作變成自動的了,這減輕的DBA的負(fù)擔(dān),不過在一些特殊情況下,還需要一些手工分析。 如果采用了CBO優(yōu)化 器,而沒有對表和索引進(jìn)行分析,沒有統(tǒng)計數(shù)據(jù),則ORACLE使用缺省的統(tǒng)計數(shù)據(jù)(至少在ORACLE 9I中是這樣),這可以從oracle的文檔上找到。使用的缺省值肯定與系統(tǒng)的實(shí)際統(tǒng)計值不一致,這可能會導(dǎo)致優(yōu)化器選擇錯誤的執(zhí)行計劃,影響數(shù)據(jù)庫的性 能。 要注意的是:雖然CBO的功能隨著ORACLE新版本的推出,功能越來越強(qiáng),但它不是能包治百病的神藥,否則就不再需要 DBA了,那我就慘了!實(shí)際上任何一個語句,隨著硬件環(huán)境與應(yīng)用數(shù)據(jù)的不同,該語句的執(zhí)行計劃可能需要隨之發(fā)生變化,這樣才能取得最好的性能。所以有 時候不在具體的環(huán)境下而進(jìn)行SQL性能調(diào)整是徒勞的。 在ORACLE8I推出的時候,ORACLE極力建議大家使用CBO,說CBO有種種好處,但是在那是ORACLE開發(fā)的應(yīng)用系統(tǒng)還是使用基于規(guī)則的優(yōu)化器,從這件事上我們可以得出這樣的結(jié)論:1) 如果團(tuán)隊的數(shù)據(jù)庫水平很高而且都熟悉應(yīng)用數(shù)據(jù)的特點(diǎn),RBO也可以取得很好的性能。 2)CBO不是很穩(wěn)定,但是一個比較有前途的優(yōu)化器,Oracle極力建議大家用是為了讓大家盡快發(fā)現(xiàn)它的BUG,以便進(jìn)一步改善,但是ORACLE為 了對自己開發(fā)的應(yīng)用系統(tǒng)負(fù)責(zé),他們還是使用了比較熟悉而且成熟的RBO。從這個事情上給我們的啟發(fā)就是:我們在以后的開發(fā)中,應(yīng)該盡量采用我們熟悉并且成 熟的技術(shù),而不要一味的采用新技術(shù),一味采用新技術(shù)并不一定能開發(fā)出好的產(chǎn)品。幸運(yùn)的是從ORACLE 10G后,CBO已經(jīng)足夠的強(qiáng)大與智能,大家可以放心的使用該技術(shù),因?yàn)镺RACLE 10G后,Oracle自己開發(fā)的應(yīng)用系統(tǒng)也使用CBO優(yōu)化器了。而且ORACLE規(guī)定,從ORACLE 10G開始,開始廢棄RBO優(yōu)化器。這句話并不是指在ORACLE 10G中不能使用RBO,而是從ORACLE 10G開始開始,不再為RBO的BUG提供修補(bǔ)服務(wù)。 在上面的第2個例子中,如果采用CBO優(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_rows_1 | 10 | 100 | 1000 | first_rows | all_rows | choose | rule。具體解釋如下: RULE為使用RBO優(yōu)化器。 CHOOSE則是根據(jù)實(shí)際情況,如果數(shù)據(jù)字典中包含被引用的表的統(tǒng)計數(shù)據(jù),即引用的對象已經(jīng)被分析,則就使用CBO優(yōu)化器,否則為RBO優(yōu)化器。 ALL_ROWS為CBO優(yōu)化器使用的第一種具體的優(yōu)化方法,是以數(shù)據(jù)的吞吐量為主要目標(biāo),以便可以使用最少的資源完成語句。 FIRST_ROWS為優(yōu)化器使用的第二種具體的優(yōu)化方法,是以數(shù)據(jù)的響應(yīng)時間為主要目標(biāo),以便快速查詢出開始的幾行數(shù)據(jù)。 FIRST_ROWS_1 | 10 | 100 | 1000 為優(yōu)化器使用的第三種具體的優(yōu)化方法,讓優(yōu)化器選擇一個能夠把響應(yīng)時間減到最小的查詢執(zhí)行計劃,以迅速產(chǎn)生查詢結(jié)果的前 n 行。該參數(shù)為ORACLE 9I新引入的。 從ORACLE V7以來,optimizer_mode參數(shù)的缺省設(shè)置應(yīng)是choose,即如果對已分析的表查詢的話選擇CBO,否則選擇RBO。在此種設(shè)置中,如果采用了CBO,則缺省為CBO中的all_rows模式。 注意:即使指定數(shù)據(jù)庫使用RBO優(yōu)化器,但有時ORACLE數(shù)據(jù)庫還是會采用CBO優(yōu)化器,這并不是ORACLE的BUG,主要是由于從ORACLE 8I后引入的許多新特性都必須在CBO下才能使用,而你的SQL語句可能正好使用了這些新特性,此時數(shù)據(jù)庫會自動轉(zhuǎn)為使用CBO優(yōu)化器執(zhí)行這些語句。 什么是優(yōu)化 優(yōu)化是選擇最有效的執(zhí)行計劃來執(zhí)行SQL語句的過程,這是在處理任何數(shù)據(jù)的語句(SELECT,INSERT,UPDATE或DELETE)中的一個重 要步驟。對Oracle來說,執(zhí)行這樣的語句有許多不同的方法,譬如說,將隨著以什么順序訪問哪些表或索引的不同而不同。所使用的執(zhí)行計劃可以決定語句能 執(zhí)行得有多快。Oracle中稱之為優(yōu)化器(Optimizer)的組件用來選擇這種它認(rèn)為最有效的執(zhí)行計劃。 由于一系列因素都 會會影響語句的執(zhí)行,優(yōu)化器綜合權(quán)衡各個因素,在眾多的執(zhí)行計劃中選擇認(rèn)為是最佳的執(zhí)行計劃。然而,應(yīng)用設(shè)計人員通常比優(yōu)化器更知道關(guān)于特定應(yīng)用的數(shù)據(jù)特 點(diǎn)。無論優(yōu)化器多么智能,在某些情況下開發(fā)人員能選擇出比優(yōu)化器選擇的最優(yōu)執(zhí)行計劃還要好的執(zhí)行計劃。這是需要人工干預(yù)數(shù)據(jù)庫優(yōu)化的主要原因。事實(shí)表明, 在某些情況下,確實(shí)需要DBA對某些語句進(jìn)行手工優(yōu)化。 注:從Oracle的一個版本到另一個版本,優(yōu)化器可能對同一語句生成不同的執(zhí)行計劃。在將來的Oracle 版本中,優(yōu)化器可能會基于它可以用的更好、更理想的信息,作出更優(yōu)的決策,從而導(dǎo)致為語句產(chǎn)生更優(yōu)的執(zhí)行計劃。第5章 ORACLE的執(zhí)行計劃 背景知識: 為了更好的進(jìn)行下面的內(nèi)容我們必須了解一些概念性的術(shù)語: 共享sql語句 為了不重復(fù)解析相同的SQL語句(因?yàn)榻馕霾僮鞅容^費(fèi)資源,會導(dǎo)致性能下降),在第一次解析之后,ORACLE將SQL語句及解析后得到的執(zhí)行計劃存放 在內(nèi)存中。這塊位于系統(tǒng)全局區(qū)域SGA(system global area)的共享池(shared buffer pool)中的內(nèi)存可以被所有的數(shù)據(jù)庫用戶共享。因此,當(dāng)你執(zhí)行一個SQL語句(有時被稱為一個游標(biāo))時,如果該語句和之前的執(zhí)行過的某一語句完全相同, 并且之前執(zhí)行的該語句與其執(zhí)行計劃仍然在內(nèi)存中存在,則ORACLE就不需要再進(jìn)行分析,直接得到該語句的執(zhí)行路徑。ORACLE的這個功能大大地提高了 SQL的執(zhí)行性能并大大節(jié)省了內(nèi)存的使用。使用這個功能的關(guān)鍵是將執(zhí)行過的語句盡可能放到內(nèi)存中,所以這要求有大的共享池(通過設(shè)置shared buffer pool參數(shù)值)和盡可能的使用綁定變量的方法執(zhí)行SQL語句。 當(dāng)你向ORACLE 提交一個SQL語句,ORACLE會首先在共享內(nèi)存中查找是否有相同的語句。這里需要注明的是,ORACLE對兩者采取的是一種嚴(yán)格匹配,要達(dá)成共享,SQL語句必須完全相同(包括空格,換行等)。 下面是判斷SQL語句是否與共享內(nèi)存中某一SQL相同的步驟: 1) 對所發(fā)出語句的文本串進(jìn)行hashed。如果hash值與已在共享池中SQL語句的hash值相同,則進(jìn)行第2步;2) 將所發(fā)出語句的文本串(包括大小寫、空白和注釋)與在第步中識別的所有已存在的SQL語句相比較。 例如: SELECT * FROM emp WHERE empno = 1000; 和下列每一個都不同 SELECT * from emp WHERE empno = 1000; SELECT * FROM EMP WHERE empno = 1000; SELECT * FROM emp WHERE empno = 2000; 在上面的語句中列值都是直接SQL語句中的,今后我們將這類sql成為硬編碼SQL或字面值SQL 使用綁定變量的SQL語句中必須使用相同的名字的綁定變量(bind variables) , 例如: a. 該2個sql語句被認(rèn)為相同 select pin , name from people where pin = :blk1.pin; select pin , name from people where pin = :blk1.pin; b. 該2個sql語句被認(rèn)為不相同 select pin , name from people where pin = :blk1.ot_ind; select pin , name from people where pin = :blk1.ov_ind; 今后我們將上面的這類語句稱為綁定變量SQL。 3) 將所發(fā)出語句中涉及的對象與第步中識別的已存在語句所涉及對象相比較。 例如: 如用戶user1與用戶user2下都有EMP表,則用戶user1發(fā)出的語句:SELECT * FROM EMP; 與 用戶user2發(fā)出的語句:SELECT * FROM EMP; 被認(rèn)為是不相同的語句,因?yàn)閮蓚€語句中引用的EMP不是指同一個表。 4) 在SQL語句中使用的捆綁變量的捆綁類型必須一致。 如果語句與當(dāng)前在共享池中的另一個語句是等同的話,Oracle并不對它進(jìn)行語法分析。而直接執(zhí)行該語句,提高了執(zhí)行效率,因?yàn)檎Z法分析比較耗費(fèi)資源。 注意的是,從oracle 8i開始,新引入了一個CURSOR_SHARING參數(shù),該參數(shù)的主要目的就是為了解決在編程過程中已大量使用的硬編碼SQL問題。因?yàn)樵趯?shí)際開發(fā)中,很多程序人員為了提高開發(fā)速度,而采用類似下面的開發(fā)方法: str_sql string; int_empno int; int_empno = 2000; str_sql = SELECT * FROM emp WHERE empno = + int_empno; int_empno = 1000; str_sql = SELECT * FROM emp WHERE empno = + int_empno; 上面的代碼實(shí)際上使用了硬編碼SQL,使我們不能使用共享SQL的功能,結(jié)果是數(shù)據(jù)庫效率不高。但是從上面的2個語句來看,產(chǎn)生的硬編碼SQL只是列值 不同,其它部分都是相同的,如果僅僅因?yàn)榱兄挡煌鴮?dǎo)致這2個語句不能共享是很可惜的,為了解決這個問題,引入了CURSOR_SHARING參數(shù),使這 類問題也可以使用共享SQL,從而使這樣的開發(fā)也可以利用共享SQL功能。聽起來不錯,ORACLE真為用戶著想,使用戶在不改變代碼的情況下還可以利用 共享SQL的功能。真的如此嗎?天上不會無緣無故的掉一個餡餅的,ORACLE對該參數(shù)的使用做了說明,建議在經(jīng)過實(shí)際測試后再改該參數(shù)的值(缺省情況 下,該參數(shù)的值為EXACT,語句完全一致才使用共享SQL)。因?yàn)橛锌赡茉撟冊撝岛?,你的硬編碼SQL是可以使用共享SQL了,但數(shù)據(jù)庫的性能反而會下 降。 我在實(shí)際應(yīng)用中已經(jīng)遇到這種情況。所以建議編寫需要穩(wěn)定運(yùn)行程序的開發(fā)人員最好還是一開始就使用綁定變量的SQL。 Rowid的概念: rowid是一個偽列,既然是偽列,那么這個列就不是用戶定義,而是系統(tǒng)自己給加上的。對每個表都有一個rowid的偽列,但是表中并不物理存儲 ROWID列的值。不過你可以像使用其它列那樣使用它,但是不能刪除改列,也不能對該列的值進(jìn)行修改、插入。一旦一行數(shù)據(jù)插入數(shù)據(jù)庫,則rowid在該行 的生命周期內(nèi)是唯一的,即即使該行產(chǎn)生行遷移,行的rowid也不會改變。 為什么使用ROWID rowid對訪問一個表中的給定的行提供了最快的訪問方法,通過ROWID可以直接定位到相應(yīng)的數(shù)據(jù)塊上,然后將其讀到內(nèi)存。我們創(chuàng)建一個索引時,該索 引不但存儲索引列的值,而且也存儲索引值所對應(yīng)的行的ROWID,這樣我們通過索引快速找到相應(yīng)行的ROWID后,通過該ROWID,就可以迅速將數(shù)據(jù)查 詢出來。這也就是我們使用索引查詢時,速度比較快的原因。 在ORACLE8以前的版本中,ROWID由FILE 、BLOCK、ROW NUMBER構(gòu)成。隨著oracle8中對象概念的擴(kuò)展,ROWID發(fā)生了變化,ROWID由OBJECT、FILE、BLOCK、ROW NUMBER構(gòu)成。利用DBMS_ROWID可以將rowid分解成上述的各部分,也可以將上述的各部分組成一個有效的rowid。 Recursive SQL概念 有時為了執(zhí)行用戶發(fā)出的一個sql語句,Oracle必須執(zhí)行一些額外的語句,我們將這些額外的語句稱之為recursive calls或recursive SQL statements。如當(dāng)一個DDL語句發(fā)出后,ORACLE總是隱含的發(fā)出一些recursive SQL語句,來修改數(shù)據(jù)字典信息,以便用戶可以成功的執(zhí)行該DDL語句。當(dāng)需要的數(shù)據(jù)字典信息沒有在共享內(nèi)存中時,經(jīng)常會發(fā)生Recursive calls,這些Recursive calls會將數(shù)據(jù)字典信息從硬盤讀入內(nèi)存中。用戶不比關(guān)心這些recursive SQL語句的執(zhí)行情況,在需要的時候,ORACLE會自動的在內(nèi)部執(zhí)行這些語句。當(dāng)然DML語句與SELECT都可能引起recursive SQL。簡單的說,我們可以將觸發(fā)器視為recursive SQL。 Row Source(行源) 用在查詢中,由上一操作返回的符合條件的行的集合,即可以是表的全部行數(shù)據(jù)的集合;也可以是表的部分行數(shù)據(jù)的集合;也可以為對上2個row source進(jìn)行連接操作(如join連接)后得到的行數(shù)據(jù)集合。 Predicate(謂詞) 一個查詢中的WHERE限制條件 Driving Table(驅(qū)動表) 該表又稱為外層表(OUTER TABLE)。這個概念用于嵌套與HASH連接中。如果該row source返回較多的行數(shù)據(jù),則對所有的后續(xù)操作有負(fù)面

溫馨提示

  • 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

提交評論