程序开发是编写sql语句的注意事项
生活随笔
收集整理的這篇文章主要介紹了
程序开发是编写sql语句的注意事项
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、操作符優(yōu)化
1、IN 操作符?用IN寫出來的SQL的優(yōu)點(diǎn)是比較容易寫及清晰易懂,這比較適合現(xiàn)代軟件開發(fā)的風(fēng)格。但是用IN的SQL性能總是比較低的,從Oracle執(zhí)行的步驟來分析用IN的SQL與不用IN的SQL有以下區(qū)別:
ORACLE 試圖將其轉(zhuǎn)換成多個(gè)表的連接,如果轉(zhuǎn)換不成功則先執(zhí)行IN里面的子查詢,再查詢外層的表記錄,如果轉(zhuǎn)換成功則直接采用多個(gè)表的連接方式查詢。由此可見用 IN的SQL至少多了一個(gè)轉(zhuǎn)換的過程。一般的SQL都可以轉(zhuǎn)換成功,但對(duì)于含有分組統(tǒng)計(jì)等方面的SQL就不能轉(zhuǎn)換了。
推薦方案:在業(yè)務(wù)密集的SQL當(dāng)中盡量不采用IN操作符,用EXISTS 方案代替。
2、NOT IN操作符?此操作是強(qiáng)列不推薦使用的,因?yàn)樗荒軕?yīng)用表的索引。
推薦方案:用NOT EXISTS 方案代替?
3、IS NULL 或IS NOT NULL操作(判斷字段是否為空) 判斷字段是否為空一般是不會(huì)應(yīng)用索引的,因?yàn)樗饕遣凰饕罩档摹?br style="padding:0px; margin:0px" /> 推薦方案:用其它相同功能的操作運(yùn)算代替,如:a is not null 改為 a>0 或a>’’等。不允許字段為空,而用一個(gè)缺省值代替空值,如申請(qǐng)中狀態(tài)字段不允許為空,缺省為申請(qǐng)。?
4、> 及 < 操作符(大于或小于操作符)?大于或小于操作符一般情況下是不用調(diào)整的,因?yàn)樗兴饕蜁?huì)采用索引查找,但有的情況下可以對(duì)它進(jìn)行優(yōu)化,如一個(gè)表有100萬記錄,一個(gè)數(shù)值型字段 A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那么執(zhí)行A>2與A>=3的效果就有很大的區(qū)別了,因 為A>2時(shí)ORACLE會(huì)先找出為2的記錄索引再進(jìn)行比較,而A>=3時(shí)ORACLE則直接找到=3的記錄索引。
5、LIKE操作符?LIKE操作符可以應(yīng)用通配符查詢,里面的通配符組合可能達(dá)到幾乎是任意的查詢,但是如果用得不好則會(huì)產(chǎn)生性能上的問題,如LIKE ‘%5400%’ 這種查詢不會(huì)引用索引,而LIKE ‘X5400%’則會(huì)引用范圍索引。 一個(gè)實(shí)際例子:用YW_YHJBQK表中營業(yè)編號(hào)后面的戶標(biāo)識(shí)號(hào)可來查詢營業(yè)編號(hào) YY_BH LIKE ‘%5400%’ 這個(gè)條件會(huì)產(chǎn)生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會(huì)利用YY_BH的索引進(jìn)行兩個(gè)范圍的查詢,性能肯定大大提高。?
6、UNION操作符?UNION在進(jìn)行表鏈接后會(huì)篩選掉重復(fù)的記錄,所以在表鏈接后會(huì)對(duì)所產(chǎn)生的結(jié)果集進(jìn)行排序運(yùn)算,刪除重復(fù)的記錄再返回結(jié)果。實(shí)際大部分應(yīng)用中是不會(huì)產(chǎn)生重復(fù)的記錄,最常見的是過程表與歷史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
這個(gè)SQL在運(yùn)行時(shí)先取出兩個(gè)表的結(jié)果,再用排序空間進(jìn)行排序刪除重復(fù)的記錄,最后返回結(jié)果集,如果表數(shù)據(jù)量大的話可能會(huì)導(dǎo)致用磁盤進(jìn)行排序。
推薦方案:采用UNION ALL操作符替代UNION,因?yàn)閁NION ALL操作只是簡單的將兩個(gè)結(jié)果合并后就返回。
select * from gc_dfys
union all
select * from ls_jg_dfys
二、SQL書寫的影響
1、同一功能同一性能不同寫法SQL的影響。
如一個(gè)SQL在A程序員寫的為 Select * from zl_yhjbqk
B 程序員寫的為 Select * from dlyx.zl_yhjbqk(帶表所有者的前綴) C程序員寫的為 Select * from DLYX.ZLYHJBQK(大寫表名) D程序員寫的為 Select * from DLYX.ZLYHJBQK(中間多了空格) 以上四個(gè)SQL在ORACLE分析整理之后產(chǎn)生的結(jié)果及執(zhí)行的時(shí)間是一樣的,但是從ORACLE共享內(nèi)存SGA的原理,可以得出ORACLE對(duì)每個(gè)SQL 都會(huì)對(duì)其進(jìn)行一次分析,并且占用共享內(nèi)存,如果將SQL的字符串及格式寫得完全相同,則ORACLE只會(huì)分析一次,共享內(nèi)存也只會(huì)留下一次的分析結(jié)果,這 不僅可以減少分析SQL的時(shí)間,而且可以減少共享內(nèi)存重復(fù)的信息,ORACLE也可以準(zhǔn)確統(tǒng)計(jì)SQL的執(zhí)行頻率。?
2、WHERE后面的條件順序影響?
WHERE子句后面的條件順序?qū)Υ髷?shù)據(jù)量表的查詢會(huì)產(chǎn)生直接的影響。如:
Select * from zl_yhjbqk where dy_dj = '1KV以下' and xh_bz=1
Select * from zl_yhjbqk where xh_bz=1 and dy_dj = '1KV以下'
以 上兩個(gè)SQL中dy_dj(電壓等級(jí))及xh_bz(銷戶標(biāo)志)兩個(gè)字段都沒進(jìn)行索引,所以執(zhí)行的時(shí)候都是全表掃描,第一條SQL的dy_dj = '1KV以下'條件在記錄集內(nèi)比率為99%,而xh_bz=1的比率只為0.5%,在進(jìn)行第一條SQL的時(shí)候99%條記錄都進(jìn)行dy_dj及xh_bz的 比較,而在進(jìn)行第二條SQL的時(shí)候0.5%條記錄都進(jìn)行dy_dj及xh_bz的比較,以此可以得出第二條SQL的CPU占用率明顯比第一條低。
3、查詢表順序的影響?
在 FROM后面的表中的列表順序會(huì)對(duì)SQL執(zhí)行性能影響,在沒有索引及ORACLE沒有對(duì)表進(jìn)行統(tǒng)計(jì)分析的情況下,ORACLE會(huì)按表出現(xiàn)的順序進(jìn)行鏈接, 由此可見表的順序不對(duì)時(shí)會(huì)產(chǎn)生十分耗服物器資源的數(shù)據(jù)交叉。(注:如果對(duì)表進(jìn)行了統(tǒng)計(jì)分析,ORACLE會(huì)自動(dòng)先進(jìn)小表的鏈接,再進(jìn)行大表的鏈接)
三、SQL語句索引的利用?
1、操作符優(yōu)化(同上)?
2、對(duì)條件字段的一些優(yōu)化?采用函數(shù)處理的字段不能利用索引,如: substr(hbs_bh,1,4)=’5400’,優(yōu)化處理:hbs_bh like ‘5400%’ trunc(sk_rq)=trunc(sysdate), 優(yōu)化處理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1) 進(jìn)行了顯式或隱式的運(yùn)算的字段不能進(jìn)行索引,如:ss_df+20>50,優(yōu)化處理:ss_df>30 ‘X’ || hbs_bh>’X5400021452’,優(yōu)化處理:hbs_bh>’5400021542’
sk_rq+5=sysdate,優(yōu)化處理:sk_rq=sysdate-5 hbs_bh=5401002554,優(yōu)化處理:hbs_bh=’ 5401002554’,注:此條件對(duì)hbs_bh 進(jìn)行隱式的to_number轉(zhuǎn)換,因?yàn)閔bs_bh字段是字符型。?
條件內(nèi)包括了多個(gè)本表的字段運(yùn)算時(shí)不能進(jìn)行索引,
如:ys_df>cx_df,無法進(jìn)行優(yōu)化
qc_bh || kh_bh=’5400250000’,優(yōu)化處理:qc_bh=’5400’ and kh_bh=’250000’
四、其他
ORACLE 的提示功能是比較強(qiáng)的功能,也是比較復(fù)雜的應(yīng)用,并且提示只是給ORACLE執(zhí)行的一個(gè)建議,有時(shí)如果出于成本方面的考慮ORACLE也可能不會(huì)按提示進(jìn) 行。根據(jù)實(shí)踐應(yīng)用,一般不建議開發(fā)人員應(yīng)用ORACLE提示,因?yàn)楦鱾€(gè)數(shù)據(jù)庫及服務(wù)器性能情況不一樣,很可能一個(gè)地方性能提升了,但另一個(gè)地方卻下降 了,ORACLE在SQL執(zhí)行分析方面已經(jīng)比較成熟,如果分析執(zhí)行的路徑不對(duì)首先應(yīng)在數(shù)據(jù)庫結(jié)構(gòu)(主要是索引)、服務(wù)器當(dāng)前性能(共享內(nèi)存、磁盤文件碎 片)、數(shù)據(jù)庫對(duì)象(表、索引)統(tǒng)計(jì)信息是否正確這幾方面分析。
oracle sql語句優(yōu)化(轉(zhuǎn)載)
(1)??????選擇最有效率的表名順序?(?只在基于規(guī)則的優(yōu)化器中有效?)?: ORACLE?的解析器按照從右到左的順序處理?FROM?子句中的表名,?FROM?子句中寫在最后的表?(?基礎(chǔ)表driving table)?將被最先處理,在?FROM?子句中包含多個(gè)表的情況下?,?你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表。如果有?3?個(gè)以上的表連接查詢?,?那就需要選擇交叉表?(intersection table)?作為基礎(chǔ)表?,?交叉表是指那個(gè)被其他表所引用的表?. (2)??????WHERE?子句中的連接順序.: ORACLE?采用自下而上的順序解析?WHERE?子句?,?根據(jù)這個(gè)原理?,?表之間的連接必須寫在其他?WHERE?條件之前?,?那些可以過濾掉最大數(shù)量記錄的條件必須寫在?WHERE?子句的末尾?. (3)??????SELECT?子句中避免使用?‘ * ‘?: ORACLE?在解析的過程中?,?會(huì)將?'*'?依次轉(zhuǎn)換成所有的列名?,?這個(gè)工作是通過查詢數(shù)據(jù)字典完成的?,?這意味著將耗費(fèi)更多的時(shí)間 (4)??????減少訪問數(shù)據(jù)庫的次數(shù): ORACLE?在內(nèi)部執(zhí)行了許多工作?:?解析?SQL?語句?,?估算索引的利用率?,?綁定變量?,?讀數(shù)據(jù)塊等; (5)??????在?SQL*Plus , SQL*Forms?和?Pro*C?中重新設(shè)置?ARRAYSIZE?參數(shù)?,?可以增加每次數(shù)據(jù)庫訪問的檢索數(shù)據(jù)量?,?建議值為?200 (6)??????使用?DECODE?函數(shù)來減少處理時(shí)間: 使用?DECODE?函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表?. (7)??????整合簡單?,?無關(guān)聯(lián)的數(shù)據(jù)庫訪問: 如果你有幾個(gè)簡單的數(shù)據(jù)庫查詢語句?,?你可以把它們整合到一個(gè)查詢中?(?即使它們之間沒有關(guān)系?) (8)??????刪除重復(fù)記錄?: 最高效的刪除重復(fù)記錄方法?(?因?yàn)槭褂昧?/span>?ROWID)?例子: DELETE ?FROM ?EMP E ?WHERE ?E.ROWID > (SELECT MIN(X.ROWID)?FROM ?EMP X ?WHERE ?X.EMP_NO = E.EMP_NO); (9)??????用?TRUNCATE?替代?DELETE?: 當(dāng)刪除表中的記錄時(shí)?,?在通常情況下?,?回滾段?(rollback segments )?用來存放可以被恢復(fù)的信息?.?如果你沒有?COMMIT?事務(wù)?,ORACLE?會(huì)將數(shù)據(jù)恢復(fù)到刪除之前的狀態(tài)?(?準(zhǔn)確地說是?恢復(fù)到執(zhí)行刪除命令之前的狀況?)?而當(dāng)運(yùn)用?TRUNCATE?時(shí)?,?回滾段不再存放任何可被恢復(fù)的信息?.?當(dāng)命令運(yùn)行后?,?數(shù)據(jù)不能被恢復(fù)?.?因此很少的資源被調(diào)用?,?執(zhí)行時(shí)間也會(huì)很短?. (?譯者按?: TRUNCATE?只在刪除全表適用?,TRUNCATE?是?DDL?不是DML) (10)??盡量多使用?COMMIT?: 只要有可能?,?在程序中盡量多使用?COMMIT,?這樣程序的性能得到提高?,?需求也會(huì)因?yàn)?/span>?COMMIT?所釋放的資源而減少?:?
COMMIT?所釋放的資源?:?
a.?回滾段上用于恢復(fù)數(shù)據(jù)的信息?.?
b.?被程序語句獲得的鎖?
c. redo log buffer?中的空間?
d. ORACLE?為管理上述?3?種資源中的內(nèi)部花費(fèi) (11)??用?Where?子句替換?HAVING?子句: 避免使用?HAVING?子句?, HAVING?只會(huì)在檢索出所有記錄之后才對(duì)結(jié)果集進(jìn)行過濾?.?這個(gè)處理需要排序?,總計(jì)等操作?.?如果能通過?WHERE?子句限制記錄的數(shù)目?,?那就能減少這方面的開銷?.?(?非?oracle?中?)?on?、where?、?having?這三個(gè)都可以加條件的子句中,?on?是最先執(zhí)行,?where?次之,?having?最后,因?yàn)?/span>?on?是先把不符合條件的記錄過濾后才進(jìn)行統(tǒng)計(jì),它就可以減少中間運(yùn)算要處理的數(shù)據(jù),按理說應(yīng)該速度是最快的,where?也應(yīng)該比?having?快點(diǎn)的,因?yàn)樗^濾數(shù)據(jù)后才進(jìn)行?sum?,在兩個(gè)表聯(lián)接時(shí)才用?on?的,所以在一個(gè)表的時(shí)候,就剩下?where?跟?having?比較了。在這單表查詢統(tǒng)計(jì)的情況下,如果要過濾的條件沒有涉及到要計(jì)算字段,那它們的結(jié)果是一樣的,只是?where?可以使用?rushmore?技術(shù),而?having?就不能,在速度上后者要慢如果要涉及到計(jì)算的字段,就表示在沒計(jì)算之前,這個(gè)字段的值是不確定的,根據(jù)上篇寫的工作流程,?where的作用時(shí)間是在計(jì)算之前就完成的,而?having?就是在計(jì)算后才起作用的,所以在這種情況下,兩者的結(jié)果會(huì)不同。在多表聯(lián)接查詢時(shí),?on?比?where?更早起作用。系統(tǒng)首先根據(jù)各個(gè)表之間的聯(lián)接條件,把多個(gè)表合成一個(gè)臨時(shí)表后,再由?where?進(jìn)行過濾,然后再計(jì)算,計(jì)算完后再由?having?進(jìn)行過濾。由此可見,要想過濾條件起到正確的作用,首先要明白這個(gè)條件應(yīng)該在什么時(shí)候起作用,然后再?zèng)Q定放在那里 (12)??減少對(duì)表的查詢: 在含有子查詢的?SQL?語句中?,?要特別注意減少對(duì)表的查詢?.?例子: ?????SELECT??TAB_NAME?FROM?TABLES?WHERE?(TAB_NAME,DB_VER) = (?SELECT TAB_NAME,DB_VER??FROM??TAB_COLUMNS ??WHERE??VERSION = 604) (13)??通過內(nèi)部函數(shù)提高?SQL?效率?.?: 復(fù)雜的?SQL?往往犧牲了執(zhí)行效率?.?能夠掌握上面的運(yùn)用函數(shù)解決問題的方法在實(shí)際工作中是非常有意義的 (14)??使用表的別名?(Alias)?: 當(dāng)在?SQL?語句中連接多個(gè)表時(shí)?,?請(qǐng)使用表的別名并把別名前綴于每個(gè)?Column?上?.?這樣一來?,?就可以減少解析的時(shí)間并減少那些由?Column?歧義引起的語法錯(cuò)誤?. (15)??用?EXISTS?替代?I?N?、?用?NOT EXISTS?替代?NOT IN?: 在許多基于基礎(chǔ)表的查詢中?,?為了滿足一個(gè)條件?,?往往需要對(duì)另一個(gè)表進(jìn)行聯(lián)接?.?在這種情況下?,?使用EXISTS(?或?NOT EXISTS)?通常將提高查詢的效率?.?在子查詢中?,NOT IN?子句將執(zhí)行一個(gè)內(nèi)部的排序和合并?.?無論在哪種情況下?,NOT IN?都是最低效的?(?因?yàn)樗鼘?duì)子查詢中的表執(zhí)行了一個(gè)全表遍歷?).?為了避免使用?NOT IN ,?我們可以把它改寫成外連接?(Outer Joins)?或?NOT EXISTS. 例子: (?高效?)?SELECT?*?FROM??EMP (?基礎(chǔ)表?) ??WHERE??EMPNO > 0 ??AND???EXISTS?(?SELECT?‘X' ?FROM?DEPT ??WHERE??DEPT.DEPTNO = EMP.DEPTNO ??AND??LOC = ‘MELB') (?低效?)?SELECT??*?FROM??EMP (?基礎(chǔ)表?) ??WHERE??EMPNO > 0 ??AND??DEPTNO?IN?(SELECTDEPTNO ??FROM??DEPT ??WHERE??LOC = ‘MELB'?) (16)??識(shí)別?'?低效執(zhí)行?'?的?SQL?語句: 雖然目前各種關(guān)于?SQL?優(yōu)化的圖形化工具層出不窮?,?但是寫出自己的?SQL?工具來解決問題始終是一個(gè)最好的方法: SELECT??EXECUTIONS , DISK_READS, BUFFER_GETS,?
ROUND?((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2?)?Hit_radio,?
ROUND?(DISK_READS/EXECUTIONS,2) Reads_per_run,?
SQL_TEXT?
FROM??V$SQLAREA?
WHERE??EXECUTIONS>0?
AND??BUFFER_GETS > 0?
AND??(BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8?
ORDER BY ??4?DESC?; (17)??用索引提高效率: 索引是表的一個(gè)概念部分?,?用來提高檢索數(shù)據(jù)的效率,?ORACLE?使用了一個(gè)復(fù)雜的自平衡?B-tree?結(jié)構(gòu)?.?通常?,?通過索引查詢數(shù)據(jù)比全表掃描要快?.?當(dāng)?ORACLE?找出執(zhí)行查詢和?Update?語句的最佳路徑時(shí)?, ORACLE優(yōu)化器將使用索引?.?同樣在聯(lián)結(jié)多個(gè)表時(shí)使用索引也可以提高效率?.?另一個(gè)使用索引的好處是?,?它提供了主鍵?(primary key)?的唯一性驗(yàn)證?.?。那些?LONG?或?LONG RAW?數(shù)據(jù)類型?,?你可以索引幾乎所有的列?.?通常?,?在大型表中使用索引特別有效?.?當(dāng)然?,?你也會(huì)發(fā)現(xiàn)?,?在掃描小表時(shí)?,?使用索引同樣能提高效率?.?雖然使用索引能得到查詢效率的提高?,?但是我們也必須注意到它的代價(jià)?.?索引需要空間來存儲(chǔ)?,?也需要定期維護(hù)?,?每當(dāng)有記錄在表中增減或索引列被修改時(shí)?,?索引本身也會(huì)被修改?.?這意味著每條記錄的?INSERT , DELETE , UPDATE?將為此多付出?4 , 5?次的磁盤?I/O .?因?yàn)樗饕枰~外的存儲(chǔ)空間和處理?,?那些不必要的索引反而會(huì)使查詢反應(yīng)時(shí)間變慢?.?。定期的重構(gòu)索引是有必要的?.?: ALTER???INDEX?<INDEXNAME>?REBUILD?<TABLESPACENAME> (18)??用?EXISTS?替換?DISTINCT?: 當(dāng)提交一個(gè)包含一對(duì)多表信息?(?比如部門表和雇員表?)?的查詢時(shí)?,?避免在?SELECT?子句中使用DISTINCT.?一般可以考慮用?EXIST?替換?, EXISTS?使查詢更為迅速?,?因?yàn)?/span>?RDBMS?核心模塊將在?子查詢的條件一旦滿足后?,?立刻返回結(jié)果?.?例子: ???????(?低效?):?
SELECT???DISTINCT??DEPT_NO,DEPT_NAME ??FROM??DEPT D , EMP E WHERE??D.DEPT_NO = E.DEPT_NO?
(?高效?):?
SELECT??DEPT_NO,DEPT_NAME ??FROM??DEPT D ??WHERE???EXISTS ( SELECT?‘X'?
FROM??EMP E ??WHERE??E.DEPT_NO = D.DEPT_NO?)?; (19)??sql?語句用大寫的?;因?yàn)?/span>?oracle?總是先解析?sql?語句,把小寫的字母轉(zhuǎn)換成大寫的再執(zhí)行 (20)??在?java?代碼中盡量少用連接符“+”連接字符串! (21)??避免在索引列上使用?NOT?通常?, 我們要避免在索引列上使用?NOT, NOT?會(huì)產(chǎn)生在和在索引列上使用函數(shù)相同的?影響?.?當(dāng)?ORACLE”?遇到”NOT,?他就會(huì)停止使用索引轉(zhuǎn)而執(zhí)行全表掃描?. (22)??避免在索引列上使用計(jì)算.?
WHERE?子句中,如果索引列是函數(shù)的一部分.優(yōu)化器將不使用索引而使用全表掃描.?
舉例?:?
低效:?
SELECT … FROM ?DEPT ?WHERE SAL * 12 > 25000;?
高效?:?
SELECT … FROM DEPT WHERE SAL > 25000/12; (23)??用?>=?替代?> 高效?:?
SELECT * FROM ?EMP ?WHERE ?DEPTNO >=4?
低效?:?
SELECT * FROM EMP WHERE DEPTNO >3?
兩者的區(qū)別在于?,?前者?DBMS?將直接跳到第一個(gè)?DEPT?等于?4?的記錄而后者將首先定位到?DEPTNO=3?的記錄并且向前掃描到第一個(gè)?DEPT?大于?3?的記錄?. (24)??用?UNION?替換?OR (?適用于索引列?) 通常情況下?,?用?UNION?替換?WHERE?子句中的?OR?將會(huì)起到較好的效果?.?對(duì)索引列使用?OR?將造成全表掃描.?注意?,?以上規(guī)則只針對(duì)多個(gè)索引列有效?.?如果有?column?沒有被索引?,?查詢效率可能會(huì)因?yàn)槟銢]有選擇?OR而降低?.?在下面的例子中?, LOC_ID?和?REGION?上都建有索引?.?
高效?:?
SELECT?LOC_ID , LOC_DESC , REGION?
FROM?LOCATION?
WHERE?LOC_ID = 10?
UNION?
SELECT?LOC_ID , LOC_DESC , REGION?
FROM?LOCATION?
WHERE?REGION = “MELBOURNE”?
低效?:?
SELECT?LOC_ID , LOC_DESC , REGION?
FROM?LOCATION?
WHERE?LOC_ID = 10?OR?REGION = “MELBOURNE”?
如果你堅(jiān)持要用?OR,?那就需要返回記錄最少的索引列寫在最前面?. (25)??用?IN?來替換?OR ? 這是一條簡單易記的規(guī)則,但是實(shí)際的執(zhí)行效果還須檢驗(yàn),在?ORACLE8i?下,兩者的執(zhí)行路徑似乎是相同的. 低效?:?
SELECT?….?FROM?LOCATION?WHERE?LOC_ID = 10?OR?LOC_ID = 20?OR?LOC_ID = 30?
高效?
SELECT?…?FROM?LOCATION?WHERE?LOC_IN ??IN?(10,20,30); (26)??避免在索引列上使用?IS NULL?和?IS NOT NULL 避免在索引中使用任何可以為空的列,?ORACLE?將無法使用該索引?.對(duì)于單列索引,如果列包含空值,索引中將不存在此記錄?.?對(duì)于復(fù)合索引,如果每個(gè)列都為空,索引中同樣不存在此記錄?.? 如果至少有一個(gè)列不為空,則記錄存在于索引中.?舉例?:?如果唯一性索引建立在表的?A?列和?B?列上?,?并且表中存在一條記錄的?A,B?值為(123,null) , ORACLE?將不接受下一條具有相同?A,B?值(?123,null?)的記錄?(?插入?).?然而如果?所有的索引列都為空,?ORACLE?將認(rèn)為整個(gè)鍵值為空而空不等于空?.?因此你可以插入?1000?條具有相同鍵值的記錄?,?當(dāng)然它們都是空?!?因?yàn)榭罩挡淮嬖谟谒饕兄?/span>?,?所以?WHERE?子句中對(duì)索引列進(jìn)行空值比較將使?ORACLE?停用該索引?. 低效?: (?索引失效?)?
SELECT?…?FROM??DEPARTMENT ??WHERE??DEPT_CODE?IS NOT NULL?;?
高效?: (?索引有效?)?
SELECT?…?FROM??DEPARTMENT ??WHERE??DEPT_CODE?>=?0; (27)??總是使用索引的第一個(gè)列?: 如果索引是建立在多個(gè)列上?,?只有在它的第一個(gè)列?(leading column)?被?where?子句引用時(shí)?,?優(yōu)化器才會(huì)選擇使用該索引?.?這也是一條簡單而重要的規(guī)則,當(dāng)僅引用索引的第二個(gè)列時(shí)?,?優(yōu)化器使用了全表掃描而忽略了索引 (28)??用?UNION-ALL?替換?UNION (?如果有可能的話?)?: 當(dāng)?SQL?語句需要?UNION?兩個(gè)查詢結(jié)果集合時(shí)?,?這兩個(gè)結(jié)果集合會(huì)以?UNION-ALL?的方式被合并?,?然后在輸出最終結(jié)果前進(jìn)行排序?.?如果用?UNION ALL?替代?UNION,?這樣排序就不是必要了?.?效率就會(huì)因此得到提高?.?需要注意的是?,?UNION ALL?將重復(fù)輸出兩個(gè)結(jié)果集合中相同記錄?.?因此各位還是?要從業(yè)務(wù)需求分析使用?UNION ALL?的可行性?. UNION?將對(duì)結(jié)果集合排序?,?這個(gè)操作會(huì)使用到?SORT_AREA_SIZE?這塊內(nèi)存?.?對(duì)于這?塊內(nèi)存的優(yōu)化也是相當(dāng)重要的?.?下面的?SQL?可以用來查詢排序的消耗量 低效:?
SELECT??ACCT_NUM, BALANCE_AMT?
FROM??DEBIT_TRANSACTIONS?
WHERE?TRAN_DATE = '31-DEC-95'?
UNION?
SELECT?ACCT_NUM, BALANCE_AMT?
FROM?DEBIT_TRANSACTIONS?
WHERE?TRAN_DATE = '31-DEC-95'?
高效?:?
SELECT?ACCT_NUM, BALANCE_AMT?
FROM?DEBIT_TRANSACTIONS?
WHERE TRAN_DATE = '31-DEC-95'?
UNION?ALL?
SELECT?ACCT_NUM, BALANCE_AMT?
FROM?DEBIT_TRANSACTIONS?
WHERE?TRAN_DATE = '31-DEC-95' (29)??用?WHERE?替代?ORDER BY?: ORDER BY?子句只在兩種嚴(yán)格的條件下使用索引?.?
ORDER BY?中所有的列必須包含在相同的索引中并保持在索引中的排列順序?.?
ORDER BY?中所有的列必須定義為非空?.?
WHERE?子句使用的索引和?ORDER BY?子句中所使用的索引不能并列?. 例如?:?
表?DEPT?包含以下列?:?
DEPT_CODE PK NOT NULL?
DEPT_DESC NOT NULL?
DEPT_TYPE NULL 低效?: (?索引不被使用?)?
SELECT?DEPT_CODE??FROM??DEPT ??ORDER BY??DEPT_TYPE?
高效?: (?使用索引?)?
SELECT?DEPT_CODE ??FROM??DEPT ??WHERE??DEPT_TYPE > 0 (30)??避免改變索引列的類型?.: 當(dāng)比較不同數(shù)據(jù)類型的數(shù)據(jù)時(shí)?, ORACLE?自動(dòng)對(duì)列進(jìn)行簡單的類型轉(zhuǎn)換?. 假設(shè)?EMPNO?是一個(gè)數(shù)值類型的索引列?.?
SELECT?… ??FROM?EMP ??WHERE???EMPNO = ‘123'?
實(shí)際上?,?經(jīng)過?ORACLE?類型轉(zhuǎn)換?,?語句轉(zhuǎn)化為?:?
SELECT?… ??FROM?EMP ?WHERE??EMPNO = TO_NUMBER(‘123')?
幸運(yùn)的是?,?類型轉(zhuǎn)換沒有發(fā)生在索引列上?,?索引的用途沒有被改變?.?
現(xiàn)在?,?假設(shè)?EMP_TYPE?是一個(gè)字符類型的索引列?.?
SELECT?… ??FROM?EMP ??WHERE?EMP_TYPE = 123?
這個(gè)語句被?ORACLE?轉(zhuǎn)換為?:?
SELECT?… ??FROM?EMP ??WHERE?TO_NUMBER(EMP_TYPE)=123?
因?yàn)閮?nèi)部發(fā)生的類型轉(zhuǎn)換?,?這個(gè)索
from:?http://lya041.blog.51cto.com/337966/680485
總結(jié)
以上是生活随笔為你收集整理的程序开发是编写sql语句的注意事项的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql dba系统学习(21)mys
- 下一篇: jqGrid使用整理