簡單整理oracle日常應用筆記。
1、采用excel表格中的資料直接粘貼資料庫記錄中,預設會在後面加一個空格“”,操作完成後一定要記得對空格比對然後修改一下。
2、查詢資料庫裡的所有表結構,
采用select * from dba_tables(sys登入);
檢視某個使用者所擁有的表:select * from all_tables where owner='scott' ;
或者 select * from dba_tables where owner='scott';
3、上午在pl/sql dev中建表時提示ora-00907: 缺失右括号,檢查sql腳本發現
eu_bctype int(50)
oracle中int為定長的類型,不能再規定其長度,需要改成number;
4、intersect運算
傳回查詢結果中相同的部分既他們的交集
1
2
3
<code>select</code> <code>* </code><code>from</code> <code>abc</code>
<code>intersect</code>
<code>select</code> <code>* </code><code>from</code> <code>abc2 ;</code>
5、minus運算
傳回在第一個查詢結果中與第二個查詢結果不相同的那部分行記錄,
即兩個結果的差集
<code>select</code> <code>* </code><code>from</code> <code>abc2</code>
<code>minus</code>
<code>select</code> <code>* </code><code>from</code> <code>abc ;</code>
6、to_char格式化小數點輸出
<code>select</code> <code>to_char(</code><code>sum</code><code>(score),9999999.99)</code><code>from</code> <code>score;</code>
7、有很多種方法可以用來找出哪些sql語句需要優化,但是很久以來,最簡單的方法都是分析儲存在vsql視圖中的緩存的sql資訊。通過vsql視圖中的緩存的sql資訊。通過vsql視圖,可以确定具有高消耗時間、cup和io讀取的sql語句
檢視總消耗時間最多的前10條sql語句
4
5
6
7
8
9
10
<code>select</code> <code>*</code>
<code>from</code> <code>(</code><code>select</code> <code>v.sql_id,</code>
<code>v.child_number,</code>
<code>v.sql_text,</code>
<code>v.elapsed_time,</code>
<code>v.cpu_time,</code>
<code>v.disk_reads,</code>
<code>rank() over(</code><code>order</code> <code>by</code> <code>v.elapsed_time </code><code>desc</code><code>) elapsed_rank</code>
<code>from</code> <code>v$sql v) a</code>
<code>where</code> <code>elapsed_rank <= 10;</code>
檢視cpu消耗時間最多的前10條sql語句
<code>rank() over(</code><code>order</code> <code>by</code> <code>v.cpu_time </code><code>desc</code><code>) elapsed_rank</code>
檢視消耗磁盤讀取最多的前10條sql語句
<code>rank() over(</code><code>order</code> <code>by</code> <code>v.disk_reads </code><code>desc</code><code>) elapsed_rank</code>
8、oracle優化操作
(1)不用“<>”或者“!=”操作符。對不等于操作符的處理會造成全表掃描,可以用“<” or “>”代替
不等于操作符是永遠不會用到索引的,是以對它的處理隻會産生全表掃描。
推薦方案:用其它相同功能的操作運算代替,
如:
<code>a<>0 改為 a>0 </code><code>or</code> <code>a<0</code>
<code>a<>’’ 改為 a>’’</code>
(2)選擇最有效率的表名順序(隻在基于規則的優化器中有效):
oracle的解析器按照從右到左的順序處理from子句中的表名,from子句中寫在最後的表(基礎表 driving table)将被最先處理,在from子句中包含多個表的情況下,你必須
選擇記錄條數最少的表作為基礎表。如果有3個以上的表連接配接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表.
(3)where子句中的連接配接順序
oracle采用自下而上的順序解析where子句,根據這個原理,表之間的連接配接必須寫在其他where條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在where子句的末尾.
(4)select子句中避免使用 ‘ * ‘
oracle在解析的過程中, 會将'*' 依次轉換成所有的列名, 這個工作是通過查詢資料字典完成的, 這意味着将耗費更多的時間
(5)減少通路資料庫的次數:
oracle在内部執行了許多工作: 解析sql語句, 估算索引的使用率, 綁定變量 , 讀資料塊等;
(6)在sql*plus , sql*forms和pro*c中重新設定arraysize參數, 可以增加每次資料庫通路的檢索資料量 ,建議值為200
(7)使用decode函數來減少處理時間:
使用decode函數可以避免重複掃描相同記錄或重複連接配接相同的表.decode(input_value,value,result[,value,result…][,default_result]);
(8)删除重複記錄:
最高效的删除重複記錄方法 ( 因為使用了rowid)例子:
<code>delete</code> <code>from</code> <code>emp e </code><code>where</code> <code>e.rowid > (</code><code>select</code> <code>min</code><code>(x.rowid)</code>
<code>from</code> <code>emp x </code><code>where</code> <code>x.emp_no = e.emp_no);</code>
(9)用truncate替代delete:
當删除表中的記錄時,在通常情況下, 復原段(rollback segments ) 用來存放可以被恢複的資訊. 如果你沒有commit事務,oracle會将資料恢複到删除之前的狀态(準确地說是
恢複到執行删除指令之前的狀況) 而當運用truncate時, 復原段不再存放任何可被恢複的資訊.當指令運作後,資料不能被恢複.是以很少的資源被調用,執行時間也會很短. (譯者
按: truncate隻在删除全表适用,truncate是ddl不是dml)
(10)用where子句替換having子句:
避免使用having子句, having 隻會在檢索出所有記錄之後才對結果集進行過濾. 這個處理需要排序,總計等操作. 如果能通過where子句限制記錄的數目,那就能減少這方面的
開銷. (非oracle中)on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最後,因為on是先把不符合條件的記錄過濾後才進行統計,它就可
以減少中間運算要處理的資料,按理說應該速度是最快的,where也應該比having快點的,因為它過濾資料後才進行sum,在兩個表聯接時才用on的,是以在一個表的時候,就
剩下where跟having比較了。在這單表查詢統計的情況下,如果要過濾的條件沒有涉及到要計算字段,那它們的結果是一樣的,隻是where可以使用rushmore技術,而having
就不能,在速度上後者要慢如果要涉及到計算的字段,就表示在沒計算之前,這個字段的值是不确定的,根據上篇寫的工作流程,where的作用時間是在計算之前就完成的,而
having就是在計算後才起作用的,是以在這種情況下,兩者的結果會不同。在多表聯接查詢時,on比where更早起作用。系統首先根據各個表之間的聯接條件,把多個表合成一
個臨時表後,再由where進行過濾,然後再計算,計算完後再由having進行過濾。由此可見,要想過濾條件起到正确的作用,首先要明白這個條件應該在什麼時候起作用,然後
再決定放在那裡。
(11)使用表的别名(alias):
當在sql語句中連接配接多個表時, 請使用表的别名并把别名字首于每個column上.這樣一來,就可以減少解析的時間并減少那些由column歧義引起的文法錯誤。
(12)用exists替代in、用not exists替代not in:
在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用exists(或not exists)通常将提高查詢的效率. 在子查詢中,not in子句将執
行一個内部的排序和合并. 無論在哪種情況下,not in都是最低效的 (因為它對子查詢中的表執行了一個全表周遊). 為了避免使用not in ,我們可以把它改寫成外連接配接(outer
joins)或not exists.
例子:
(高效)select * from emp (基礎表) where empno > 0 and exists (select ‘x' from dept where dept.deptno = emp.deptno and loc = ‘melb')
(低效)select * from emp (基礎表) where empno > 0 and deptno in(select deptno from dept where loc = ‘melb')
(13)sql語句用大寫的;因為oracle總是先解析sql語句,把小寫的字母轉換成大寫的再執行
(14)避免在索引列上使用not
我們要避免在索引列上使用not, not會産生和在索引列上使用函數相同的影響. 當oracle”遇到”not,他就會停止使用索引轉而執行全表掃描.
(15)避免在索引列上使用計算.
where子句中,如果索引列是函數的一部分.優化器将不使用索引而使用全表掃描.
舉例:
低效:
select … from dept where sal * 12 > 25000;
高效:
select … from dept where sal > 25000/12;
(16)用>=替代>
<code>高效:</code>
<code>select</code> <code>* </code><code>from</code> <code>emp </code><code>where</code> <code>deptno >=4</code>
<code>低效:</code>
<code>select</code> <code>* </code><code>from</code> <code>emp </code><code>where</code> <code>deptno >3</code>
兩者的差別在于, 前者dbms将直接跳到第一個dept等于4的記錄而後者将首先定位到deptno=3的記錄并且向前掃描到第一個dept大于3的記錄.
(17)避免在索引列上使用is null和is not null
避免在索引中使用任何可以為空的列,oracle将無法使用該索引.對于單列索引,如果列包含空值,索引中将不存在此記錄. 對于複合索引,如果每個列都為空,索引中同樣不存在此記錄. 如果至少有一個列不為空,則記錄存在于索引中.舉例: 如果唯一性索引建立在表的a列和b列上, 并且表中存在一條記錄的a,b值為(123,null) , oracle将不接受下一條具有相同a,b值(123,null)的記錄(插入). 然而如果所有的索引列都為空,oracle将認為整個鍵值為空而空不等于空. 是以你可以插入1000 條具有相同鍵值的記錄,當然它們都是空! 因為空值不存在于索引列中,是以where子句中對索引列進行空值比較将使oracle停用該索引.
低效: (索引失效)
select … from department where dept_code is not null;
高效: (索引有效)
select … from department where dept_code >=0;
(18)索引的弊端
a. 如果檢索資料量超過30%的表中記錄數.使用索引将沒有顯著的效率提高.
b. 在特定情況下, 使用索引也許會比全表掃描慢, 但這是同一個數量級上的差別. 而通常情況下,使用索引比全表掃描要塊幾倍乃至幾千倍!
(19)可能引起全表掃描的操作
在索引列上使用not或者“<>”
對索引列使用函數或者計算
not in操作
通配符位于查詢字元串的第一個字元
is null或者is not null
多列索引,但它的第一個列并沒有被where子句引用
9、oracle sql分頁查詢處理
分頁取11到20的記錄,兩種查詢方法,如下,
第一種的速度會比較快點,因為在tab1這層先過濾掉了一部分資料,第二種方法到最外層再進行處理
11
12
13
14
15
16
17
18
19
20
21
22
<code>--分頁查詢1</code>
<code>select</code> <code>tab2.*</code>
<code> </code><code>from</code> <code>(</code><code>select</code> <code>tab1.*, rownum row_num</code>
<code> </code><code>from</code> <code>(</code>
<code> </code><code>--把需要分頁的sql直接放進來就行了</code>
<code> </code><code>select</code> <code>t.* </code><code>from</code> <code>t_t_dept t</code>
<code> </code>
<code> </code><code>) tab1</code>
<code> </code><code>where</code> <code>rownum<21</code>
<code> </code><code>) tab2</code>
<code>where</code> <code>tab2.row_num >10</code>
<code>--分頁查詢2</code>
<code>where</code> <code>tab2.row_num </code><code>between</code> <code>11 </code><code>and</code> <code>20</code>