oracle開發知識點

1. 分區表

    Oracle 建議如果單個表超過2G就最好對其進行分區。 對大表的查詢、增加、修改等操作可以分解到表的不同分區來並行執行,可使運行速度更快;

    1) Range分區

  Range分區呢是應用範圍比較廣的表分區方式,它是以列的值的範圍來做爲分區的劃分條件,將記錄存放到列值所 在的range分區中,比如按照時間劃分,2008年1季度的數據放到a分區,08年2季度的數據放到b分區,因此在創建的時候呢,需要你指定基於的列, 以及分區的範圍值,如果某些記錄暫無法預測範圍,可以創建maxvalue分區,所有不在指定範圍內的記錄都會被存儲到maxvalue所在分區中,並且 支持指定多列做爲依賴列

     2) Hash分區

  通常呢,對於那些無法有效劃分範圍的表,可以使用hash分區,這樣對於提高性能還是會有一定的幫助。hash 分區會將表中的數據平均分配到你指定的幾個分區中,列所在分區是依據分區列的hash值自動分配,因此你並不能控制也不知道哪條記錄會被放到哪個分區 中,hash分區也可以支持多個依賴列。

     3) List分區

     你能控制記錄存儲在哪個分區。它的分區列只能有一個 ,要創建一個default分區存儲那些不在指定範圍內的記錄。     

 

 

2. sql優化

   1)索引列

       a) 避免在索引列上使用NOT 通常,我們要避免在索引列上使用NOT,  當ORACLE”遇到”NOT,他就會停止使用索引轉而執行全表掃描.

      b) 避免在索引列上使用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;

        c)總是使用索引的第一個列:
如果索引是建立在多個列上, 只有在它的第一個列(leading column)被where 子句引用時, 優化器纔會選擇使用該索引. 這也是一條簡單而重要的規則,當僅引用索引的第二個列時, 優化器使用了全表掃描而忽略了索引

       d)某些SELECT 語句中的WHERE 子句不使用索引. 這裏有一些例子.

       在下面的例子裏, (1)‘!=' 將不使用索引. 記住, 索引只能告訴你什麼存在於表中, 而不能告訴你什麼不存在於表中. (2) ‘||'是字符連接函數. 就象其他函數那樣, 停用了索引. (3) ‘+'是數學函數. 就象其他數學函數那樣, 停用了索引. (4)相同的索引列不能互相比較,(5)索引列上使用計算.(5)內部發生的類型轉換, (6)%在第一個字符。這個索引將不會被用到. 這將會啓用全表掃描. 舉例:
低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;

       e) 合理的索引設計:
例:表record有620000行,試看在不同的索引下,下面幾個SQL的運行情況:
語句A
SELECT count(*) FROM record
WHERE date >'19991201' and date< '19991214‘ and amount=2000
語句B
SELECT count(*) FROM record
WHERE date>'19990901' and place IN ('BJ','SH')
語句C
SELECT date,sum(amount) FROM record   group by date
1 在date上建有一個非聚集索引
A:(25秒)
B:(27秒)
C:(55秒)
分析:
date上有大量的重複值,在非聚集索引下,數據在物理上隨機存放在數據頁上,在範圍查找時,必須執行一次表掃描才能找到這一範圍內的全部行。
2 在date上的一個聚集索引
A:(14秒)
B:(14秒)
C:(28秒)
分析:
在聚集索引下,數據在物理上按順序在數據頁上,重複值也排列在一起,因而在範圍查找時,可以先找到這個範圍的起末點,且只在這個範圍內掃描數據頁,避免了大範圍掃描,提高了查詢速度。
3 在place,date,amount上的組合索引
A:(26秒)
C:(27秒)
B:(<1秒)
分析:
這是一個不很合理的組合索引,因爲它的前導列是place,第一和第二條SQL沒有引用place,因此也沒有利用上索引;第三個SQL使用了place,且引用的所有列都包含在組合索引中,形成了索引覆蓋,所以它的速度是非常快的。
4 在date,place,amount上的組合索引
A: (<1秒)
B:(<1秒)
C:(11秒)
分析:
這是一個合理的組合索引。它將date作爲前導列,使每個SQL都可以利用索引,並且在第一和第三個SQL中形成了索引覆蓋,因而性能達到了最優。

總結1
缺省情況下建立的索引是非聚集索引,但有時它並不是最佳的;合理的索引設計要建立在對各種查詢的分析和預測上。一般來說:
有大量重複值、且經常有範圍查詢(between, ><,>=,<=)和order by、group by發生的列,考慮建立聚集索引;
經 常同時存取多列,且每列都含有重複值可考慮建立組合索引;在條件表達式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引。比如在僱員 表的“性別”列上只有“男”與“女”兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。
組合索引要儘量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。



   2) 儘早過濾掉更多的記錄

      2.1) 選擇最有效率順序

        a)表名順序(只在基於規則的優化器中有效):
     ORACLE 的解析器按照從右到左的順序處理FROM 子句中的表名,FROM 子句中寫在最後的表(基礎表driving table)將被最先處理,在FROM 子句中包含多個表的情況下,你必須選擇記錄條數最少的表作爲基礎表。如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作爲基礎表, 交叉表是指那個被其他表所引用的表.

        b) WHERE 子句中的連接順序.:
ORACLE 採用自下而上的順序解析WHERE 子句,根據這個原理,表之間的連接必須寫在其他WHERE 條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE 子句的末尾.

    

       2.2) 分組查詢

         a) 用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 進行過濾。

           b) 優化GROUP BY:
提高GROUP BY 語句的效率, 可以通過將不需要的記錄在GROUP BY 之前過濾掉.下面兩個
查詢返回相同結果但第二個明顯就快了許多.
低效:
SELECT JOB , AVG(SAL)
FROM EMP
GROUP by JOB
HAVING JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER'
高效:
SELECT JOB , AVG(SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER'
GROUP by JOB



    3)避免排序

           a) 替代IN、用NOT EXISTS 替代NOT IN:
在許多基於基礎表的查詢中,爲了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率. 在子查詢中,NOT IN 子句將執行一個內部的排序和合並. 無論在哪種情況下,NOT IN 都是最低效的(因爲它對子查詢中的表執行了一個全表遍歷). 爲了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
例子: 查詢位置在MELB的部門裏的所有員工
(高效)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 DEP
TNO FROM DEPT WHERE LOC = ‘MELB')

        b)  替換DISTINCT:
當提交一個包含一對多表信息(比如部門表和僱員表)的查詢時,避免在SELECT 子句中使用DISTINCT. 一般可以考慮用EXIST 替換, EXISTS 使查詢更爲迅速,因爲RDBMS 核心模塊將在子查詢的條件一旦滿足後,立刻返回結果. 例子: 查詢有僱員的部門
(低效):
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);  


 


    6)減少解析時間

       a)SELECT 子句中避免使用‘ * ‘:
    ORACLE 在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的, 這意味着將耗費更多的時間

       b)使用表的別名(Alias):
當在SQL 語句中連接多個表時, 請使用表的別名並把別名前綴於每個Column 上.這樣一來, 就可以減少解析的時間並減少那些由Column 歧義引起的語法錯誤.

       c) sql 語句用大寫的;因爲oracle 總是先解析sql 語句,把小寫的字母轉換成大寫的再執行

    7)避免使用耗費資源的操作:
帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY 的SQL 語句會啓動SQL 引擎執行耗費資源的排序(SORT)功能. DISTINCT 需要一次排序操作, 而其他的至少需要執行兩次排序. 通常, 帶有UNION, MINUS , INTERSECT 的SQL 語句都可以用其他方式重寫. 如果你的數據庫的SORT_AREA_SIZE 調配得好, 使用UNION , MINUS, INTERSECT 也是可以考慮
的, 畢竟它們的可讀性很強


3.存儲
   1) 表空間由一個或者多個文件組成,組成表空間的文件可以是文件系統上的各種文件;表空間包含段。
   2) 段由一個或者多個區段組成,有table段、index段等。包含在表空間中,但是可以跨表空間內的多個文件。
   3) 區段是磁盤上一組邏輯連續的塊。區段只在一個表空間中,二期總是在該表空間內的一個文件中。
   4) 塊是數據庫中最小的分配單位,也是數據庫使用的最小I/O單位;在給段分配空間的時候,分配空間至少爲一個塊的整數被大小。

 

4.時間

imestamp 數據類型ITPUB個人空間` N pc!B1SUh1P ITPUB個人空間+mvA_:u%EF/E
date數據類型的主要問題是他粒度不能足夠區別出兩個事件哪個先發生。oracle已在date數據類型上擴展出來了timestamp數據類型,他包括了任何date數據類型的年月日時分秒的信息,而且包括了小數秒的信息。


   Oracle使用天來作爲消逝時間的單位,d1-d2 NUMBER 返回D1和D2之間相差的天數。該值是一個數值,其小數部分代表一天的幾分之幾。

   默認格式是:DD-MON-RR。

  SELECT TO_CHAR(date1,'MM/DD/YYYY HH24:MI:SS') "Date" FROM date_table;

 

dt1-dt2 INTERVAL 返回DT1和DT2之間的時間間隔。
 SYSDATE 返回當前的系統時間。 SELECT SYSDATE FROM DUAL;

 

在某段時間內:
select * from up_date where update between to_date('2007-07-07 00:00:00','yyyy-mm-dd hh24:mi:ss') and to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss')
select * from up_date where update < to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') and update >= to_date('2007-07-07 00:00:00','yyyy-mm-dd hh24:mi:ss')

 

 

5.sql 語句

  (1) 分頁  查詢 30到40之間記錄

      SELECT * FROM
(
SELECT
row_ .*, rownum rownum_
FROM (SELECT * FROM TABLE_NAME) row_
WHERE
rownum <= 40
)
WHERE
rownum_ >= 30

* 注意使用rownum只能使用<號,=號只能用於1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章