oracle 数据语句优化,oracle 查询语句优化录
最近,因?yàn)榘l(fā)現(xiàn)以前使用的數(shù)據(jù)查詢語(yǔ)句的效率越來(lái)越差,導(dǎo)致每次進(jìn)行大量數(shù)據(jù)的操作都需要耗一個(gè)小時(shí)以上.這速度實(shí)在是太龜慢了,簡(jiǎn)直是無(wú)法忍受了.本人決定親自拿把殺豬刀砍向它,好給它顏色瞧瞧.經(jīng)過(guò)一系列的測(cè)試后發(fā)現(xiàn),原來(lái)罪灰禍?zhǔn)质遣樵償?shù)據(jù)時(shí)因?yàn)檎Z(yǔ)句的組合方式不對(duì)導(dǎo)致了數(shù)據(jù)庫(kù)查詢慢,當(dāng)時(shí)那個(gè)淚崩啊,感覺(jué)這實(shí)在是太坑爹了.
因此,我就借此機(jī)會(huì)把我所知道的能提高查詢效率的方法整理了一下,并分享出來(lái)和大家共同學(xué)習(xí).
一. 書(shū)寫(xiě)順序方面
我們常常會(huì)在寫(xiě)oracle語(yǔ)句后發(fā)現(xiàn)該語(yǔ)句的執(zhí)行時(shí)間過(guò)長(zhǎng),效率低下的問(wèn)題.然而我們有沒(méi)有想過(guò)怎么會(huì)發(fā)生這樣的情況呢?
我大致歸納為兩個(gè)方面:
第一: 不了解oracle的解析器解析sql語(yǔ)句的順序
a. 數(shù)據(jù)表的處理順序
oracle 在解析一個(gè)查詢語(yǔ)句FROM后面的一系列數(shù)據(jù)表是按照從右往左的順序進(jìn)行的.也就是說(shuō)最后的數(shù)據(jù)表將是最先被oracle處理的,所以我們?cè)趯?xiě)多個(gè)表關(guān)聯(lián)的查詢語(yǔ)句時(shí),把數(shù)據(jù)量最小的表或者是經(jīng)過(guò)條件篩選后得到數(shù)據(jù)量最小的表放到最后,數(shù)據(jù)量大的表就放在最前面.
select col1, col2 from t1, t2 where t1.id = t2.id ?and t2.sex = 'male';
上面的語(yǔ)句中數(shù)據(jù)表t2是第一個(gè)被oracle處理的數(shù)據(jù)表,然后就是t1.
b.where 條件的處理順序
oracle 在解析查詢語(yǔ)句制定執(zhí)行計(jì)劃時(shí),針對(duì)where后面的查詢條件的解析是按照從下往上的順序進(jìn)行的.也就說(shuō)查詢的子條件越處于where的后面,它被oracle處理優(yōu)先級(jí)就越高.所以我們可以把能過(guò)濾大量數(shù)據(jù)的條件放到最后,讓oracle優(yōu)先處理它從而返回一個(gè)最小數(shù)據(jù)集,好讓oracle在后續(xù)的過(guò)濾工作基于該最小數(shù)據(jù)集進(jìn)行,來(lái)縮小整個(gè)查詢時(shí)間.
select col1, col2 from t1, t2 where t1.id = t2.id and t2.sex = 'male' and t2.etime>=trunc(sysdate-1)?and t2.etime
上面語(yǔ)句中的查詢條件t2.channel = '0' 將會(huì)被oracle最先解析.
第二:查詢方式的錯(cuò)誤選擇導(dǎo)致效率低下
平時(shí)工作下來(lái)積累的一些優(yōu)化建議如下:
1. where 后面的條件盡量避免涉及null值得判斷,為什么呢?那是因?yàn)橐坏┥婕暗搅薾ull的判斷,oracle將不會(huì)走該字段所涉及的索引而觸發(fā)全表掃描.
select col1 from t where t.servid is not null; --效率低
如果t表的servid中有索引的話,那么本次查詢將拋棄索引,走全表掃描.建議如果真的需要判斷的話,可以定義該字段的默認(rèn)值為0或者其它值.
2. where 后面盡量不要使用多個(gè)or把條件組合起來(lái), 可以使用union/union all來(lái)實(shí)現(xiàn)
select col3, col5 from t where (t.servid = 5 or t.servid = 90) and t.channel = 1; --效率低
select col3, col5 from t where t.servid = 5 and t.channel = 1
union
select col3, col5 from t where t.servid = 90 and t.channel = 1; ? --效率高
3. 條件中盡量避免給有索引的字段進(jìn)行不等操作(!=或<>),因?yàn)橐坏┻M(jìn)行不等操作,oracle將不會(huì)走現(xiàn)有的索引轉(zhuǎn)而走全表掃描.
4. 返回結(jié)果使用具體的列名來(lái)代替星號(hào)(*),因?yàn)閛racle 遇到星號(hào) 需要另外去查對(duì)應(yīng)的字典從而把所有的列名給轉(zhuǎn)換出來(lái),這導(dǎo)致了需要消耗時(shí)間.
5. 訪問(wèn)數(shù)據(jù)表的次數(shù)盡量少
6. 使用exists 來(lái)代替in , not exists 代替not in 來(lái)提交數(shù)據(jù)的訪問(wèn)速度
7. 不要對(duì)有索引的字段進(jìn)行函數(shù)操作或者運(yùn)算操作,不然會(huì)導(dǎo)致這些字段不會(huì)走索引
select col1 from t where (t.servid * 2) = 10; --效率低下
select col1 from t where t.servid = 10/ 2; --效率高
8. 當(dāng)需要?jiǎng)h除大量數(shù)據(jù)的時(shí)候,如果條件允許的話,可以使用truncate 來(lái)代替delete. 因?yàn)閐elete 時(shí)數(shù)據(jù)庫(kù)時(shí)需要維護(hù)一系列的信息以便進(jìn)行回滾等操作,而truncate 則不是要額外維護(hù)這些信息,直接高效清空數(shù)據(jù)庫(kù)表.
9. 如果表有分區(qū)的話,盡量使用分區(qū)進(jìn)行查詢.因?yàn)橥?lèi)的數(shù)據(jù)都集中在一個(gè)分區(qū)(數(shù)據(jù)塊)里面,查詢是不需要跨塊查詢,從而效率較高
10. ?比較大小時(shí)盡量使用等于號(hào)來(lái)提高效率
select col1 from t where t.servid > 60; --效率比較低下,因?yàn)閐ml會(huì)直接跳到60這個(gè)記錄上,然后在往前掃大于60的記錄,額外的動(dòng)作,額外的消耗.
select col1 from t where t.servid >= 61; --效率高
11. 判斷是否存在某條記錄時(shí),使用exists 來(lái)提高效率,它可以避免進(jìn)行全表掃描
select count(*) from t where t.name = 'Gavin'; ?--效率低下,進(jìn)行全表掃描
select count(1) from dual where exists(select null from t where t.name='Gavin'); --效率高
12. ?union all 效率高于union ,因?yàn)閡nion 相對(duì)于union all 來(lái)說(shuō)多了一個(gè)去重的操作
13. 可以使用視圖來(lái)加速結(jié)果的搜索
14. 如果對(duì)有索引的字段進(jìn)行模糊搜索時(shí),盡量使用單右邊模糊匹配查詢,這樣就可以使它能有效的使用對(duì)應(yīng)的索引.
select col5 from t where t.name like '%Ga%'; --效率低,不走索引
select col5 from t where t.name like 'Ga%'; ?--效率高,走索引
總結(jié)
以上是生活随笔為你收集整理的oracle 数据语句优化,oracle 查询语句优化录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: Oracle PCTfree assm,
 - 下一篇: 手机linux内核下载,Linux Ke