官术网_书友最值得收藏!

5.2 Oracle實(shí)現(xiàn)數(shù)據(jù)訪問的方法

Oracle的RDBMS在訪問數(shù)據(jù)時(shí)最根本上使用三種訪問方法:

● 全表掃描。

● 通過ROWID。

● 使用索引。

當(dāng)Oracle決定使用索引時(shí)會(huì)使用ROWID來訪問數(shù)據(jù),當(dāng)沒有索引或者不選擇使用索引時(shí)就使用全表掃描的方式。

5.2.1 全表掃描(FULL TABLE SCAN--FTS)

在使用全表掃描時(shí),Oracle讀取表中所有的行,此時(shí)通過多塊讀操作可以大大減少I/O的次數(shù),利用多塊讀可以大大提高全表掃描的速度,只有在全表掃描的情況下才能使用多塊讀。在較大的表上不建議使用全表掃描,如果讀取表的數(shù)據(jù)總量超過5%~10%,那么通常進(jìn)行全表掃描。并行查詢可能會(huì)使得我們的路徑選擇采用全表掃描。

即使在表上創(chuàng)建了索引,是否使用該索引由Oracle根據(jù)CBO優(yōu)化器計(jì)算的結(jié)果選擇,用戶無法干預(yù)(當(dāng)然DBA可以修改參數(shù)或者SQL語句使得走索引)。

Oracle讀取表中所有的行、多塊讀操作可以大大地減少IO的次數(shù)、利用多塊讀可以大大地提高全表掃描的速度、只有在全表掃描的情況下才能使用多塊讀。

在較大的表上不建議使用全表掃描、如果讀取表的數(shù)據(jù)總量超過5%—10%,那么通常進(jìn)行全表掃描。并行查詢可能會(huì)使得我們的路徑選擇采用全表掃描,如下例所示。

例子5-1 并行查詢可能會(huì)使得我們的路徑選擇采用全表掃描

5.2.2 通過行ID(ROWID)

對(duì)于表對(duì)象,在向表中插入數(shù)據(jù)時(shí)隱含會(huì)創(chuàng)建該行的ROWID,ROWID是數(shù)據(jù)行所存儲(chǔ)的數(shù)據(jù)塊地址,這樣就以最快的速度找到該行數(shù)據(jù)。如下例所示,查詢行ID,我們通過比較,看全表掃描和通過行ID哪個(gè)更快。

ROWID指出了數(shù)據(jù)文件、塊號(hào)、行號(hào),通過ROWID是Oracle數(shù)據(jù)庫中讀取單行數(shù)據(jù)最快速的方法。這種方法不是采用多塊讀,而是采用單塊讀的方式。

例子5-2 查詢行ID比較全表掃描和通過行ID哪個(gè)更快

5.2.3 使用索引

通過索引找到數(shù)據(jù)行的ROWID,然后通過ROWID直接到表中查找數(shù)據(jù),這種方式稱為索引查找或索引掃描。由于一個(gè)ROWID對(duì)應(yīng)一個(gè)數(shù)據(jù)行,因此這種方式采用的也是單塊讀。在索引中,除了存儲(chǔ)每個(gè)索引值,還存儲(chǔ)相應(yīng)的ROWID,索引掃描分為兩步:

01 掃描索引得到相應(yīng)的ROWID。

02 通過找到的ROWID從表中讀取相應(yīng)的數(shù)據(jù),

每次采用的都是單塊I/O讀,由于索引小,而且經(jīng)常使用,因此通常被cache到內(nèi)存中,并且第一步通常是邏輯讀(數(shù)據(jù)可以從內(nèi)存中得到),由于表數(shù)據(jù)比較大,因此第二步通常是物理讀,并且性能較低。

索引改進(jìn)性能的程度取決于兩個(gè)因素:

● 數(shù)據(jù)的選擇性。

● 表數(shù)據(jù)在數(shù)據(jù)塊上的分布。

如果選擇性很高(例如身份證號(hào)碼),則根據(jù)索引值返回的ROWID很少,如果選擇性很低(例如國家)則返回的ROWID很多,那么索引的性能將會(huì)大大降低(返回的數(shù)據(jù)少,I/O壓力小)。

如果選擇性很高,但是相關(guān)的行在表中的存儲(chǔ)位置并不互相靠近,則會(huì)進(jìn)一步減少索引的益處,如果匹配索引值的數(shù)據(jù)分散在表的多個(gè)數(shù)據(jù)塊中,則必須從表中選擇多個(gè)單獨(dú)的塊以滿足查詢,基于索引的讀取是單塊讀取,如果使用全表掃描,使用的是多塊讀取以便快速掃描表,因此全表掃描不見得比索引掃描速度慢,關(guān)鍵看數(shù)據(jù)對(duì)象數(shù)據(jù)塊的分散程度。

當(dāng)訪問的行數(shù)較少時(shí),SELECT、UPDATE、DELETE+WHERE條件可以從索引中得到更多的好處。一般來說,增加索引會(huì)帶來insert語句性能的下降,如果根據(jù)未索引列update索引列,那么也會(huì)帶來性能的降低。大量的delete也會(huì)因?yàn)樗饕拇嬖诙鴮?dǎo)致性能降低。因此我們要分析具體的情況,判斷索引和DML語句之間的關(guān)系。

通過索引找到數(shù)據(jù)行的ROWID、然后通過ROWID直接到表中查找數(shù)據(jù),這種方式稱為索引查找或者索引掃描。因?yàn)橐粋€(gè)ROWID對(duì)應(yīng)一個(gè)數(shù)據(jù)行,因此這種方式采用的也是單塊讀。在索引中,除了存儲(chǔ)每個(gè)索引值、還存儲(chǔ)相應(yīng)的ROWID,索引掃描分為兩步:

01 掃描索引得到相應(yīng)的ROWID。

02 通過找到的ROWID從表中讀取相應(yīng)的數(shù)據(jù)。

每次采用的都是單塊IO讀,因?yàn)樗饕?,而且?jīng)常使用,因此通常被cache到內(nèi)存中,因此第一步通常是邏輯讀(數(shù)據(jù)可以從內(nèi)存中得到),因?yàn)楸頂?shù)據(jù)比較大、因此第二步讀通常是物理讀,因此性能較低。

例子5-3 訪問路徑走主鍵索引的查詢

訪問路徑走的是主鍵索引,因此是INDEX UNIQUE SCAN,首先是索引掃描,然后是根據(jù)索引查找到的ROWID進(jìn)行表的訪問。

主站蜘蛛池模板: 庆安县| 卓资县| 福州市| 双牌县| 广西| 临猗县| 通河县| 如东县| 白朗县| 孝义市| 丁青县| 宁晋县| 渑池县| 汤原县| 龙井市| 亳州市| 河北区| 广丰县| 丹寨县| 溧水县| 商南县| 平罗县| 衡南县| 湘潭市| 襄垣县| 安丘市| 桂阳县| 乌拉特中旗| 千阳县| 汉川市| 廉江市| 马尔康县| 东台市| 奉新县| 新津县| 永登县| 临潭县| 长治县| 大洼县| 曲沃县| 咸丰县|