天天看點

Oracle 日常應用筆記

簡單整理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 &lt;= 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)不用“&lt;&gt;”或者“!=”操作符。對不等于操作符的處理會造成全表掃描,可以用“&lt;” or “&gt;”代替

不等于操作符是永遠不會用到索引的,是以對它的處理隻會産生全表掃描。

推薦方案:用其它相同功能的操作運算代替,

如:

<code>a&lt;&gt;0 改為 a&gt;0 </code><code>or</code> <code>a&lt;0</code>

<code>a&lt;&gt;’’ 改為 a&gt;’’</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 &gt; (</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 &gt; 0  and  exists (select ‘x'  from dept  where  dept.deptno = emp.deptno  and  loc = ‘melb')

(低效)select  * from  emp (基礎表)  where  empno &gt; 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 &gt; 25000; 

高效: 

select … from dept where sal &gt; 25000/12;

(16)用&gt;=替代&gt;

<code>高效:</code>

<code>select</code> <code>* </code><code>from</code>  <code>emp  </code><code>where</code>  <code>deptno &gt;=4</code>

<code>低效:</code>

<code>select</code> <code>* </code><code>from</code> <code>emp </code><code>where</code> <code>deptno &gt;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 &gt;=0;

(18)索引的弊端

a. 如果檢索資料量超過30%的表中記錄數.使用索引将沒有顯著的效率提高. 

b. 在特定情況下, 使用索引也許會比全表掃描慢, 但這是同一個數量級上的差別. 而通常情況下,使用索引比全表掃描要塊幾倍乃至幾千倍!

(19)可能引起全表掃描的操作

在索引列上使用not或者“&lt;&gt;”

對索引列使用函數或者計算

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&lt;21</code>

<code>        </code><code>) tab2</code>

<code>where</code> <code>tab2.row_num &gt;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>