国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

Oracle數(shù)據(jù)庫SQL語句性能調(diào)整的基本原則

瀏覽:159日期:2023-11-28 14:23:32
這篇論壇文章(賽迪網(wǎng)技術(shù)社區(qū))詳細(xì)的介紹了Oracle數(shù)據(jù)庫SQL語句性能調(diào)整的基本原則,具體內(nèi)容請參考下文。

一、問題的提出

在應(yīng)用系統(tǒng)開發(fā)初期,由于開發(fā)數(shù)據(jù)庫數(shù)據(jù)比較少,對于查詢SQL語句,復(fù)雜視圖的的編寫等體會不出SQL語句各種寫法的性能優(yōu)劣,但是如果將應(yīng)用系統(tǒng)提交實(shí)際應(yīng)用后,隨著數(shù)據(jù)庫中數(shù)據(jù)的增加,系統(tǒng)的響應(yīng)速度就成為目前系統(tǒng)需要解決的最主要的問題之一。系統(tǒng)優(yōu)化中一個很重要的方面就是SQL語句的優(yōu)化。對于海量數(shù)據(jù),劣質(zhì)SQL語句和優(yōu)質(zhì)SQL語句之間的速度差別可以達(dá)到上百倍,可見對于一個系統(tǒng)不是簡單地能實(shí)現(xiàn)其功能就可,而是要寫出高質(zhì)量的SQL語句,提高系統(tǒng)的可用性。

在多數(shù)情況下,Oracle使用索引來更快地遍歷表,優(yōu)化器主要根據(jù)定義的索引來提高性能。但是,如果在SQL語句的where子句中寫的SQL代碼不合理,就會造成優(yōu)化器刪去索引而使用全表掃描,一般就這種SQL語句就是所謂的劣質(zhì)SQL語句。在編寫SQL語句時我們應(yīng)清楚優(yōu)化器根據(jù)何種原則來刪除索引,這有助于寫出高性能的SQL語句。

二、SQL語句編寫注意問題

下面就某些SQL語句的where子句編寫中需要注意的問題作詳細(xì)介紹。在這些where子句中,即使某些列存在索引,但是由于編寫了劣質(zhì)的SQL,系統(tǒng)在運(yùn)行該SQL語句時也不能使用該索引,而同樣使用全表掃描,這就造成了響應(yīng)速度的極大降低。

1. IS NULL 與 IS NOT NULL

不能用null作索引,任何包含null值的列都將不會被包含在索引中。即使索引有多列這樣的情況下,只要這些列中有一列含有null,該列就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高性能。任何在where子句中使用is null或is not null的語句優(yōu)化器是不允許使用索引的。

2. 聯(lián)接列

對于有聯(lián)接的列,即使最后的聯(lián)接值為一個靜態(tài)值,優(yōu)化器是不會使用索引的。我們一起來看一個例子,假定有一個職工表(employee),對于一個職工的姓和名分成兩列存放(FIRST_NAME和LAST_NAME),現(xiàn)在要查詢一個叫比爾.克林頓(Bill Cliton)的職工。

下面是一個采用聯(lián)接查詢的SQL語句:

select * from employss

where

first_name||''||last_name ='Beill Cliton';

上面這條語句完全可以查詢出是否有Bill Cliton這個員工,但是這里需要注意,系統(tǒng)優(yōu)化器對基于last_name創(chuàng)建的索引沒有使用。

當(dāng)采用下面這種SQL語句的編寫,Oracle系統(tǒng)就可以采用基于last_name創(chuàng)建的索引。

Select * from employee

where

first_name ='Beill' and last_name ='Cliton';

遇到下面這種情況又如何處理呢?如果一個變量(name)中存放著Bill Cliton這個員工的姓名,對于這種情況我們又如何避免全程遍歷,使用索引呢?可以使用一個函數(shù),將變量name中的姓和名分開就可以了,但是有一點(diǎn)需要注意,這個函數(shù)是不能作用在索引列上。下面是SQL查詢腳本:

select * from employee

where

first_name = SUBSTR('&&name',1,INSTR('&&name',' ')-1)

and

last_name = SUBSTR('&&name',INSTR('&&name’,' ')+1)

3. 帶通配符(%)的like語句

同樣以上面的例子來看這種情況。目前的需求是這樣的,要求在職工表中查詢名字中包含cliton的人。可以采用如下的查詢SQL語句:

select * from employee where last_name like '%cliton%';

這里由于通配符(%)在搜尋詞首出現(xiàn),所以O(shè)racle系統(tǒng)不使用last_name的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,通配符如此使用會降低查詢速度。然而當(dāng)通配符出現(xiàn)在字符串其他位置時,優(yōu)化器就能利用索引。在下面的查詢中索引得到了使用:

select * from employee where last_name like 'c%';

4. Order by語句

ORDER BY語句決定了Oracle如何將返回的查詢結(jié)果排序。Order by語句對要排序的列沒有什么特別的限制,也可以將函數(shù)加入列中(象聯(lián)接或者附加等)。任何在Order by語句的非索引項(xiàng)或者有計(jì)算表達(dá)式都將降低查詢速度。

仔細(xì)檢查order by語句以找出非索引項(xiàng)或者表達(dá)式,它們會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應(yīng)絕對避免在order by子句中使用表達(dá)式。

5. NOT

我們在查詢時經(jīng)常在where子句使用一些邏輯表達(dá)式,如大于、小于、等于以及不等于等等,也可以使用and(與)、or(或)以及not(非)。NOT可用來對任何邏輯運(yùn)算符號取反。下面是一個NOT子句的例子:

... where not (status ='VALID')

如果要使用NOT,則應(yīng)在取反的短語前面加上括號,并在短語前面加上NOT運(yùn)算符。NOT運(yùn)算符包含在另外一個邏輯運(yùn)算符中,這就是不等于(<>)運(yùn)算符。換句話說,即使不在查詢where子句中顯式地加入NOT詞,NOT仍在運(yùn)算符中,見下例:

... where status <>'INVALID';

再看下面這個例子:

select * from employee where salary<>3000;

對這個查詢,可以改寫為不使用NOT:

select * from employee where salary<3000 or salary>3000;

雖然這兩種查詢的結(jié)果一樣,但是第二種查詢方案會比第一種查詢方案更快些。第二種查詢允許Oracle對salary列使用索引,而第一種查詢則不能使用索引。

6. IN和EXISTS

有時候會將一列和一系列值相比較。最簡單的辦法就是在where子句中使用子查詢。在where子句中可以使用兩種格式的子查詢。

第一種格式是使用IN操作符:

... where column in(select * from ... where ...);

第二種格式是使用EXIST操作符:

... where exists (select 'X' from ...where ...);

我相信絕大多數(shù)人會使用第一種格式,因?yàn)樗容^容易編寫,而實(shí)際上第二種格式要遠(yuǎn)比第一種格式的效率高。在Oracle中可以幾乎將所有的IN操作符子查詢改寫為使用EXISTS的子查詢。

第二種格式中,子查詢以‘select 'X'開始。運(yùn)用EXISTS子句不管子查詢從表中抽取什么數(shù)據(jù)它只查看where子句。這樣優(yōu)化器就不必遍歷整個表而僅根據(jù)索引就可完成工作(這里假定在where語句中使用的列存在索引)。相對于IN子句來說,EXISTS使用相連子查詢,構(gòu)造起來要比IN子查詢困難一些。

通過使用EXIST,Oracle系統(tǒng)會首先檢查主查詢,然后運(yùn)行子查詢直到它找到第一個匹配項(xiàng),這就節(jié)省了時間。Oracle系統(tǒng)在執(zhí)行IN子查詢時,首先執(zhí)行子查詢,并將獲得的結(jié)果列表存放在在一個加了索引的臨時表中。在執(zhí)行子查詢之前,系統(tǒng)先將主查詢掛起,待子查詢執(zhí)行完畢,存放在臨時表中以后再執(zhí)行主查詢。這也就是使用EXISTS比使用IN通常查詢速度快的原因。

同時應(yīng)盡可能使用NOT EXISTS來代替NOT IN,盡管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查詢效率更高。

=====================================================

Oracle的SQL調(diào)優(yōu)是一個復(fù)雜的主題,甚至是需要整本書來介紹OracleSQL調(diào)優(yōu)的細(xì)微差別。不過有一些基本的規(guī)則是每個OracleDBA都需要跟從的,這些規(guī)則可以改善他們系統(tǒng)的性能。SQL調(diào)優(yōu)的目標(biāo)是簡單的:

消除不必要的大表全表搜索:不必要的全表搜索導(dǎo)致大量不必要的I/O,從而拖慢整個數(shù)據(jù)庫的性能。調(diào)優(yōu)專家首先會根據(jù)查詢返回的行數(shù)目來評價SQL。在一個有序的表中,如果查詢返回少于40%的行,或者在一個無序的表中,返回少于7%的行,那么這個查詢都可以調(diào)整為使用一個索引來代替全表搜索。對于不必要的全表搜索來說,最常見的調(diào)優(yōu)方法是增加索引。可以在表中加入標(biāo)準(zhǔn)的B樹索引,也可以加入bitmap和基于函數(shù)的索引。要決定是否消除一個全表搜索,你可以仔細(xì)檢查索引搜索的I/O開銷和全表搜索的開銷,它們的開銷和數(shù)據(jù)塊的讀取和可能的并行執(zhí)行有關(guān),并將兩者作對比。在一些情況下,一些不必要的全表搜索的消除可以通過強(qiáng)制使用一個index來達(dá)到,只需要在SQL語句中加入一個索引的提示就可以了。

在全表搜索是一個最快的訪問方法時,將小表的全表搜索放到緩存中,調(diào)優(yōu)專家應(yīng)該確保有一個專門的數(shù)據(jù)緩沖用作行緩沖。在Oracle7中,你可以使用altertablexxxcache語句,在Oracle8或以上,小表可以被強(qiáng)制為放到KEEP池中緩沖。

確保最優(yōu)的索引使用:對于改善查詢的速度,這是特別重要的。有時Oracle可以選擇多個索引來進(jìn)行查詢,調(diào)優(yōu)專家必須檢查每個索引并且確保Oracle使用正確的索引。它還包括bitmap和基于函數(shù)的索引的使用。

確保最優(yōu)的JOIN操作:有些查詢使用NESTEDLOOPjoin快一些,有些則是HASHjoin快一些,另外一些則是sort-mergejoin更快。

這些規(guī)則看來簡單,不過它們占SQL調(diào)優(yōu)任務(wù)的100%,并且它們也無需完全懂得OracleSQL的內(nèi)部運(yùn)作。以下我們來簡單概覽以下OracleSQL的優(yōu)化。

我們首先簡要查看Oracle的排序,并且看一看排序操作是如何影響性能的。

調(diào)整Oracle的排序操作

排序是SQL語法中一個小的方面,但很重要,在Oracle的調(diào)整中,它常常被忽略。當(dāng)使用createindex、ORDERBY或者GROUPBY的語句時,Oracle數(shù)據(jù)庫將會自動執(zhí)行排序的操作。通常,在以下的情況下Oracle會進(jìn)行排序的操作:

使用Orderby的SQL語句

使用Groupby的SQL語句

在創(chuàng)建索引的時候

進(jìn)行tablejoin時,由于現(xiàn)有索引的不足而導(dǎo)致SQL優(yōu)化器調(diào)用MERGESORT

當(dāng)與Oracle建立起一個session時,在內(nèi)存中就會為該session分配一個私有的排序區(qū)域。如果該連接是一個專用的連接(dedicatedconnection),那么就會根據(jù)init.ora中sort_area_size參數(shù)的大小在內(nèi)存中分配一個ProgramGlobalArea(PGA)。如果連接是通過多線程服務(wù)器建立的,那么排序的空間就在large_pool中分配。不幸的是,對于所有的session,用做排序的內(nèi)存量都必須是一樣的,我們不能為需要更大排序的操作分配額外的排序區(qū)域。因此,設(shè)計(jì)者必須作出一個平衡,在分配足夠的排序區(qū)域以避免發(fā)生大的排序任務(wù)時出現(xiàn)磁盤排序(disksorts)的同時,對于那些并不需要進(jìn)行很大排序的任務(wù),就會出現(xiàn)一些浪費(fèi)。當(dāng)然,當(dāng)排序的空間需求超出了sort_area_size的大小時,這時將會在TEMP表空間中分頁進(jìn)行磁盤排序。磁盤排序要比內(nèi)存排序大概慢14,000倍。

上面我們已經(jīng)提到,私有排序區(qū)域的大小是有init.ora中的sort_area_size參數(shù)決定的。每個排序所占用的大小由init.ora中的sort_area_retained_size參數(shù)決定。當(dāng)排序不能在分配的空間中完成時,就會使用磁盤排序的方式,即在Oracle實(shí)例中的臨時表空間中進(jìn)行。

磁盤排序的開銷是很大的,有幾個方面的原因。首先,和內(nèi)存排序相比較,它們特別慢;而且磁盤排序會消耗臨時表空間中的資源。Oracle還必須分配緩沖池塊來保持臨時表空間中的塊。無論什么時候,內(nèi)存排序都比磁盤排序好,磁盤排序?qū)钊蝿?wù)變慢,并且會影響Oracle實(shí)例的當(dāng)前任務(wù)的執(zhí)行。還有,過多的磁盤排序?qū)頵reebufferwaits的值變高,從而令其它任務(wù)的數(shù)據(jù)塊由緩沖中移走。

標(biāo)簽: Oracle 數(shù)據(jù)庫
主站蜘蛛池模板: 日本视频在线免费看 | 亚洲高清国产一区二区三区 | 久草视频在线资源站 | 国产最新自拍 | 欧美一级在线看 | 一级黄色录相片 | 亚洲美女网址 | 国产成人狂喷潮在线观看2345 | 久久久久久久性潮 | 最近中文字幕免费视频 | 久久99国产精品久久 | 免费观看一级特黄三大片视频 | 成人欧美视频 | 俄罗斯美女毛片 | 欧美特欧美特级一片 | 在线成人97观看 | 99视频在线看 | 真人一级毛片免费观看视频 | 久久视频在线播放视频99re6 | 又黄又www | 久久久久女人精品毛片九一 | 日本三级网站在线观看 | 91久久国产精品 | 手机看片1024欧美日韩你懂的 | 成人小视频在线播放 | 精品欧美高清一区二区免费 | 国产精品不卡在线 | 久久99精品久久久久久秒播放器 | 颜值超高的女神啪啪 | 中文字幕亚洲一区二区va在线 | 精品在线视频免费观看 | 国产欧美成人 | 一区二区三区精品视频 | 韩国三级大全久久网站 | 暖暖视频日韩欧美在线观看 | 美日韩一区二区三区 | 成网站在线观看人免费 | 日韩在线一区二区三区视频 | 九九精品在线观看 | 一级全免费视频播放 | 国产一区二区在线播放 |