Where子句中的連接順序
ORACLE采用自下而上的順序解析WHERE子句
根據這個原理表之間的連接必須寫在其他WHERE條件之前 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾
舉例
(低效)select … from table t where tsal > and tjobtype = and < (select count(*) from table t where tpno = ttno;(高效)select … from table t where < (select count(*) from table t where tpno = ttno and tsal > and tjobtype = ;Select子句中避免使用 *
當你想在select子句中列出所有的column時使用動態SQL列引用 * 是一個方便的方法
不幸的是這是一個非常低效的方法
實際上ORACLE在解析的過程中會將 * 依次轉換成所有的列名 這個工作是通過查詢數據字典完成的 這意味著將耗費更多的時間
減少訪問數據庫的次數
當執行每條SQL語句時ORACLE在內部執行了許多工作
解析SQL語句估算索引的利用率綁定變量讀數據塊等等
由此可見減少訪問數據庫的次數就能實際上減少ORACLE的工作量
舉例
題目——我要查找編號為學生的信息
(低效)select nameagegenderaddress from t_student where id = ;select nameagegenderaddress from t_student where id = ;(高效)select anameaageagenderaaddressbnamebagebgenderbaddress from t_student at_student b where aid = and bid = ;使用Decode函數來減少處理時間
使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表
舉例
(低效)select count(*) sum(banace) from table where dept_id = and name like anger%;select count(*) sum(banace) from table where dept_id = and name like anger%;(高效)select count(decode(dept_idXYZnull)) count_count(decode(dept_idXYZnull)) count_sum(decode(dept_iddept_idnull)) sum_sum(decode(dept_iddept_idnull)) sum_from tablewhere name like anger%;整合簡單無關聯的數據庫訪問
如果你有幾個簡單的數據庫查詢語句你可以把它們整合到一個查詢中(即使它們之間沒有關系)舉例
(低效)select name from table where id = ;select name from table where id = ;select name from table where id = ;(高效)select tname tname tnamefrom table t table t table twhere tid(+) = and tid(+) = and tid(+) =
【注上面例子雖然高效但是可讀性差需要量情而定啊!】[nextpage]
刪除重復記錄
最高效的刪除重復記錄方法 ( 因為使用了ROWID)舉例
delete from table twhere trowid > (select min(trowid) from table t where tid = tid)盡量不要使用having子句可以考慮用where替換
having只會在檢索出所有記錄之後才對結果集進行過濾 這個處理需要排序總計等操作
如果能通過where子句限制記錄的數目那就能減少這方面的開銷[nextpage]
盡量用表的別名
當在SQL語句中連接多個表時請使用表的別名並把別名前綴於每個Column上
這樣一來就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤
用exists替代in(發現好多程序員不知道這個怎麼用)
在許多基於基礎表的查詢中為了滿足一個條件往往需要對另一個表進行聯接
在這種情況下使用exists(或not exists)通常將提高查詢的效率
舉例
(低效)select … from table t where tid > and pno in (select no from table where name like www%)(高效)select … from table t where tid > and exists (select from table t where tpno = tno and name like www%)用not exists替代not in
在子查詢中not in子句將執行一個內部的排序和合並
無論在哪種情況下not in都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷)
為了避免使用not in我們可以把它改寫成外連接(Outer Joins)或not exists
用exists替換distinct
當提交一個包含一對多表信息的查詢時避免在select子句中使用distinct 一般可以考慮用exists替換舉例
(低效)select distinct ddept_no ddept_name from t_dept d t_emp e where ddept_no = edept_no;(高效)select ddept_no ddept_name from t_dept d where exists (select from t_emp where ddept_no = edept_no)exists使查詢更為迅速因為RDBMS核心模塊將在子查詢的條件一旦滿足後立刻返回結果
用表連接替換exists
通常來說采用表連接的方式比exists更有效率
舉例
(低效)select ename from emp e where exists (select from dept where dept_no = edept_no and dept_cat = W)SELECT ENAME(高效)select ename from dept d emp e where edept_no = ddept_no and dept_cat = W;避免在索引列上使用is null和is not null避免在索引中使用任何可以為空的列ORACLE將無法使用該索引
對於單列索引如果列包含空值索引中將不存在此記錄對於復合索引如果每個列都為空索引中同樣不存在此記錄如果至少有一個列不為空則記錄存在於索引中
舉例
如果唯一性索引建立在表的A列和B列上 並且表中存在一條記錄的AB值為(null)ORACLE將不接受下一條具有相同AB值(null)的記錄(插入)然而如果所有的索引列都為空ORACLE將認為整個鍵值為空而空不等於空
因此你可以插入 條具有相同鍵值的記錄當然它們都是空!
因為空值不存在於索引列中所以WHERE子句中對索引列進行空值比較將使ORACLE停用該索引
From:http://tw.wingwit.com/Article/program/Oracle/201311/16701.html