[收藏]SQL優(yōu)化

          Posted on 2006-03-20 20:53 ikingqu 閱讀(763) 評論(1)  編輯  收藏 所屬分類: DataBase
          最近做項目發(fā)現(xiàn)很多SQL沒有優(yōu)化: 現(xiàn)在總結(jié)幾種優(yōu)化方式.
          ?首先先了解一個SQL語句的執(zhí)行過程分3步: 語法分析(parase)與編譯,執(zhí)行,取數(shù)據(jù).
          1: 在語法分析與編譯時:oracle 使用哈希函數(shù)為SQL語句在庫緩存中分配一個SQL區(qū),
          首先檢查語句是否存在,若在,則查詢數(shù)據(jù)庫字典、檢查必須的權(quán)限。
          若無,需要語法分析與編譯。所以SQL語句存在與內(nèi)存中,將減少分析,編譯時間。
          SQL語句的分析與編譯占整個語句運行過程的60%的時間,SQL優(yōu)化的目標就是減少分析與編譯的時間,共享代碼。

          查詢SQL語句分析與編譯的時間:
          select * from v$sysstat
          where name in ('parse time cpu','parse time elapsed','parse count (hard)')

          一個SQL語句的響應(yīng)時間(elapsed time )應(yīng)該是服務(wù)時間+等待時間.
          服務(wù)時間= CPU執(zhí)行時間.
          等待時間 可以從v$system_event
          select total_waits, total_timeouts, time_waited, average_wait ,event
          from v$system_event
          where event='latch free'
          所以解析一個SQL語句的平均等待時間是"等待時間/parse count" 這個值接近0
          通過數(shù)據(jù)字典v$sqlare,可以查詢到頻繁被分析與編譯的SQL語句.應(yīng)該減少SQL語句的分析與編譯的次數(shù).

          2: 將常用的實體駐留內(nèi)存.
          為了減少分析與編譯時間,可以將常用的的實體如: 存儲過程,包等,盡可能駐留在內(nèi)存區(qū)域.
          ?1)預留內(nèi)存空間. sql> show parameter shared_pool_reserved_size
          ?????? 2)將頻繁使用的實體駐留在內(nèi)存中. 在使用DBMS_SHARED_POOL程序包前,必須首先運行系統(tǒng)提供的程序包: dbmspool.sql 和prvtpool.plb
          ?在加載這兩個程序包后,自動生成所需的包.
          ????? 加載: sql> @/u01/app/oracle/product/8.17/rdbms/admin/dbmspool.sql
          ?????????? sql> @/u01/app/oracle/product/8.17/rdbms/admin/prvtpool.sql
          ????? 包DBMS_SHARED_POOL包含以下存儲過程.
          ????? dbms_shared_pool.keep 用于將實體保存內(nèi)存. dbms_shared_pool.keep(object in varchar2,[type in char default p]);
          ???????????????????????????? object 表示參數(shù)名, type 表示被駐留內(nèi)存的實體類型;P 表示存儲過程,C表示光標,R表示觸發(fā)器,默認P
          ???????
          ????? dbms_shared_pool.unkeep 用于取消被設(shè)置進入內(nèi)存的實體. dbms_shared_pool.unkeep(object in varchar2,[type in char default p]);
          ???????????????????????????? object 表示參數(shù)名, type 表示被駐留內(nèi)存的實體類型;P 表示存儲過程,C表示光標,R表示觸發(fā)器,默認P
          ?????
          ????? dbms_shared_pool.size(minsize in number)

          ????? select name ,type ,source_size+code_size+parsed_size+error_size "total bytes"
          ????? from dba_object_size
          ????? where owner='SCOTT'

          3: 創(chuàng)建索引.
          ?? select index_name,table_owner, table_name, tablespace_name from all_indexes
          ??
          ?? select user_indexes.TABLE_NAME, user_indexes.INDEX_NAME,uniqueness, column_name
          ?? from user_ind_columns ,user_indexes
          ?? where user_ind_columns.INDEX_NAME=user_indexes.INDEX_NAME
          ?? and user_ind_columns.TABLE_NAME=user_indexes.TABLE_NAME
          ?? order by user_indexes.TABLE_TYPE,user_indexes.TABLE_NAME,user_indexes.INDEX_NAME,user_ind_columns.COLUMN_POSITION

          4: 創(chuàng)建聚簇(cluster): 是一組存儲在一起的有共同列或經(jīng)常一起使用的表,被聚簇的兩個表只有一個數(shù)據(jù)段.聚簇表在存儲時,在物理層將子表合并到父表中,這樣就少了表的連接時間.

          5: 創(chuàng)建哈希索引.
          ?
          6: SQL優(yōu)化器: 基于成本的優(yōu)化器CBO(cose_based)和基于規(guī)則RBO(rule_based)
          ?? sql> show parameter OPTIMIZER_MODE
          ?? 可以修改參數(shù)文件: initSID.ora,增加: optimizer_Mode={CHOOSE| RULE| FIRST_ROWS|ALL_ROWS}
          ? all_rows , first_rows(n)基于成本; rule 基于規(guī)則,choose基于規(guī)則、成本。
          ? /*+ ordered*/
          ? /*+ rule */
          ? /*+ first_rows(50) */

          ? /*+ordered star*/
          ? 寫發(fā):?
          ? alter system flush shared_pool;
          select /*+ rule */ aa from visit

          原文鏈接:http://www.aygfsteel.com/yanmin/archive/2006/03/20/36332.html

          Feedback

          # re: [轉(zhuǎn)]SQL優(yōu)化  回復  更多評論   

          2006-03-20 23:41 by 風向逆轉(zhuǎn) - Java無限
          SQL優(yōu)化 補充
          作者blog:http://blog.csdn.net/baggio785/

          Sql優(yōu)化是一項復雜的工作,以下的一些基本原則是本人看書時所記錄下來的,很明確且沒什么廢話:
          1. 索引的使用:
          (1).當插入的數(shù)據(jù)為數(shù)據(jù)表中的記錄數(shù)量的10%以上,首先需要刪除該表的索引來提高數(shù)據(jù)的插入效率,當數(shù)據(jù)插入后,再建立索引。
          (2).避免在索引列上使用函數(shù)或計算,在where子句中,如果索引是函數(shù)的一部分,優(yōu)化器將不再使用索引而使用全表掃描。如:
          低效:select * from dept where sal*12 >2500;
          高效:select * from dept where sal>2500/12;
          (3).避免在索引列上使用not和 “!=”,索引只能告訴什么存在于表中,而不能告訴什么不存在于表中,當數(shù)據(jù)庫遇到not 和 “!=”時,就會停止使用索引而去執(zhí)行全表掃描。
          (4).索引列上>=代替>
          低效:select * from emp where deptno > 3
          高效:select * from emp where deptno >=4
          兩者的區(qū)別在于,前者dbms將直接跳到第一個deptno等于4的記錄,而后者將首先定位到deptno等于3的記錄并且向前掃描到第一個deptno大于3的。
          (5).非要對一個使用函數(shù)的列啟用索引,基于函數(shù)的索引是一個較好的方案。
          2. 游標的使用:
          當在海量的數(shù)據(jù)表中進行數(shù)據(jù)的刪除、更新、插入操作時,用游標處理的效率是最慢的,但是游標又是必不可少的,所以正確使用游標十分重要:
          (1). 在數(shù)據(jù)抽取的源表中使用時間戳,這樣每天的維表數(shù)據(jù)維護只針對更新日期為最新時間的數(shù)據(jù)來進行,大大減少需要維護的數(shù)據(jù)記錄數(shù)。
          (2). 在insert和update維表時都加上一個條件來過濾維表中已經(jīng)存在的記錄,例如:
          insert into dim_customer select * from ods_customer where ods_customer.code not exists (dim_customer.code)
          ods_customer為數(shù)據(jù)源表。dim_customer為維表。
          (3). 使用顯式的游標,因為隱式的游標將會執(zhí)行兩次操作,第一次檢索記錄,第二次檢查too many rows這個exception,而顯式游標不執(zhí)行第二次操作。
          3. 據(jù)抽取和上載時的sql優(yōu)化:
          (1). Where 子句中的連接順序:
          oracle采用自下而上的順序解析where子句,根據(jù)這個原理,表之間的連接必須寫在其他where條件之前,那些可以過濾掉大量記錄的條件必須寫在where子句的末尾。如:
          低效:select * from emp e where sal>5000 and job = ‘manager’ and 25<(select count (*) from emp where mgr=e.empno);
          高效:select * from emp e where 25<(select count(*) from emp where mgr=e.empno) and sal>5000 and job=’manager’;
          (2). 刪除全表時,用truncate 替代 delete,同時注意truncate只能在刪除全表時適用,因為truncate是ddl而不是dml。
          (3). 盡量多使用commit
          只要有可能就在程序中對每個delete,insert,update操作盡量多使用commit,這樣系統(tǒng)性能會因為commit所釋放的資源而大大提高。
          (4). 用exists替代in ,可以提高查詢的效率。
          (5). 用not exists 替代 not in
          (6). 優(yōu)化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 having job=’president’ or job=’manager’ group by job;
          (7). 有條件的使用union-all 替代 union:這樣做排序就不必要了,效率會提高3到5倍。
          (8). 分離表和索引
          總是將你的表和索引建立在不同的表空間內(nèi),決不要將不屬于oracle內(nèi)部系統(tǒng)的對象存放到system表空間內(nèi)。同時確保數(shù)據(jù)表空間和索引表空間置于不同的硬盤控制卡控制的硬盤上。



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=623666

          posts - 4, comments - 5, trackbacks - 0, articles - 60

          Copyright © ikingqu

          主站蜘蛛池模板: 沙田区| 太和县| 宁津县| 大港区| 石楼县| 馆陶县| 弥渡县| 永春县| 临西县| 江永县| 象山县| 获嘉县| 乌恰县| 五大连池市| 南京市| 高安市| 太康县| 道孚县| 营山县| 固原市| 吉木萨尔县| 武乡县| 莫力| 新竹县| 望谟县| 琼结县| 中西区| 紫云| 河池市| 上虞市| 类乌齐县| 威宁| 定陶县| 瓦房店市| 潼关县| 合肥市| 临澧县| 陇西县| 阿荣旗| 凤山县| 马龙县|