1、Overview:
Oracle shared server主要用于允許多user進程能夠共享有限數量的servers。
在dedicated server環境中,每個user 進程都會分配到一個server進程,但如果這些server進程不能完全被利用,常處于idle狀態,就會造成內存和cpu的浪費。
當使用shared server模式,user進程是動態的被分配到可以被任何user進程共享的server進程上的。當dispatcher進程獲得一個user 進程請求后會將其放入請求隊列,以便server進程可以處理該請求并將結果返回給dispatcher的response隊列。隨后 dispatcher進程會將response隊列中的結果返回給user進程。
Oracle Shared Server主要用于下面的情況:當dedicated Server的系統對于system開銷相對較大;在訪問的資源上存在限制。
2、對dispatchers的監控:
1)可以通過v$MTS視圖獲得關于連接和session的會話以及當前使用的使用的數據信息。如果sessions的設置低于實際的dispatcher的設置,MAXIMUM_CONNECTIONS的默認值是參數SESSIONS的值。
2)V$DISPATCHER視圖查詢dispatcher的繁忙率:
select network “protocol”, status “status”, sum(owned) “clients”, sum(busy) * 100/(sum(busy)+sum(idle)) “busy rate” from v$dispatche group by network;
note:在選擇dispatcher數量的時候,應該考慮客戶端的數量對于dispatcher的繁忙比率。如果一個dispatcher的繁忙比率 超過50%,就需要考慮增加dispatcher的數量。如果發現部分dispatcher經常處于idle的狀態,應該考慮減少dispatcher的 數量。
可用下面的SQL查看users sessions是否在等待dispatchers:
select decode(sum(totalq), 0, ‘no responses’, sum(wait)/sum(totalq)) “average wait time” from v$queue q, v$dispatcher d where q.type = ‘DISPATCHER’ AND q.paddr = d.paddr;
如果觀察到大量的等待比率并不斷增長,需要考慮增加dispatcher的數量。
增加或減少dispatcher使用:
alter system set mts_dispatchers = ‘protocol, number’;
執行上述語句后只有新的連接建立才會使用new增加的dispatcher。
2)此外,可以使用視圖V$DISPATCHER_RATE視圖來分析沖突。它分組顯示了cur、avg、max的統計信息。如果使用shared Server的性能不理想,則cur的值將接近max的值,對此應該考慮增加dispatcher的數量。如果發現shared Server性能良好,cur值遠遠低于max的值,可以考慮降低dispatcher的個數。
3、對Shared Server的監控:
當PMON后臺進程發現當前存在的shared Servers都處在忙碌狀態,Oracle shared Server進程就會被是動態創建的創建。當然此時MAX_SHARED_SERVERS的值必須大于實際的servers值。當然,如果PMON檢測到 當前有shared servers存在idle狀態的,則會減少相應的shared servers的數量,直到數量達到SHARED_SERVERS的值。所以不必太多的考慮shared servers的狀態。但是有時需要調整SHARED_SERVERS和MAX_SHARED_SERVERS的參數的大小。
對此,可以使用視圖V$SHARED_SERVER視圖獲得shared servers的當前信息。
select name, requests, busy*100/(busy+idle) “busy %”, status from v$shared_server where status != ’QUIT’;
此外,可以查看每個請求的平均等待時間:
select decode(totalq, 0, ‘No Requests’, wait/totalq ||’ hundredths of seconds’ )”Average Wait Time Per Requests” from v$queue where type = ‘COMMON’;
4、監控進程的作用:查看共享連接。如果覺得user程序有問題或是某個進程似乎做了很多操作,可能需要查看當前user的共享連接。對此可以使用 v$session視圖查看應用的狀態和使用的連接類型,可以使用v$circuit獲得相應的server、session和dispatcher的 addresses。
5、shared server和memory 使用:之前有說過,當使用shared server模式時,部分稱為UGA(user global area)的數據將被存放在shared pool中,同時session的data Components被存放在large pool中。如果沒有設置large pool,將存放在shared pool中。
從總體將使用shared server模式,內存的開支減少了。
shared servers使用UGA用于sorts,此模式下,應該設置SORT_AREA_RETAINED_SIZE相對小于SORT_AREA_SIZE,以便可以快速釋放內存給其他user。
6、troubleshooting:常見問題有:
1)所有共享連接都失敗時,查看Oracle net listener在running。
2)查看是否在建立shared connection時存在Oracle net配置的錯誤”TNS_”
3)不要輕易在OS層kill掉user的server進程,建議使用alter system kill session。如果使用dispatcher連接的,kill掉dispatcher進程會更糟,會影響其他user。
4)dispatchers和servers都是后臺進程,所以在設置PROCESSES時要考慮相應的數量。
5)如果參數INSTANCE_NAME, SERVICE_NAMES 或 DB_DOMAIN 沒有被設置,或是設置不正確,則其不能進行自動instance注冊。
• V$CIRCUIT: Contains information about user connections to the database
• V$DISPATCHER: Provides information on the dispatcher processes
• V$DISPATCHER_RATE: Provides rate statistics for the dispatcher processes
• V$QUEUE: Contains information on the multithread message queues
• V$MTS: Contains information for tuning the Oracle shared server
• V$SESSION: Lists session information for each current session
• V$SHARED_SERVER: Contains information about the shared server processes
eg:
SELECT d.network network, d.name disp, s.username oracle_user,
s.sid sid,s.serial# serial#, p.username os_user,
p.terminal terminal, s.program program
FROM v$dispatcher d, v$circuit c, v$session s, v$process p
WHERE d.paddr = c.dispatcher(+)
AND c.saddr = s.saddr(+)
AND s.paddr = p.addr (+)
order by d.network, d.name, s.username
1、選擇適當的物理結構:為了達到讀寫盡可能快的目的,必須考慮下面的問題:
1)如果application對rows的訪問是按照groups進行的,則需要考慮使用clusters的方式才存儲,但clusters對于大量的DML操作會影響性能,所以要考慮application中DML和select操作的數量。
2)對于較大規模的表,使用單獨的表空間。對于一個partitioned表,考慮使用多個表空間,從而平均分配磁盤的使用。
3)對于9i中可以允許在同一個DB中有多block size,因此,row size較大的可以有較大的block size。如果設置較大的block size,有助于全表掃描的應用的性能提高。
4)對于小的small transaction占用undo space的回滾信息少,大transaction占用的undo space多,所以所需的free undo space多。
5)對于較大的查詢,可以考慮使用多server 進程進程并發查詢。
2、數據的訪問方法:為了提高性能,可以使用下面的數據訪問方法:clusters;indexes:b-tree(普通和翻轉關鍵字)、位圖、Function based;索引組織表;固化視圖。
1)Clusters:是將一組一個或多個因為有共享columns所以有相同數據塊的表放在一起的方法。這些數據塊會經常被同時訪問或join。這種方法可以使DBA對數據庫非規范化,而對user和programmer是透明的。
它在一定程度上降低了磁盤I/O,使用clustered table可以很好的改善join的效率。每個cluster關鍵字對于多行且值相同的情況下,只會存儲一次,所以占用存儲空間較小。
但是對于全表掃描,clustered表比nonclustered 表慢很多。
cluster的類型有:
①index cluster:它使用一個被稱作cluster index的索引維持cluster中的數據。在index cluster中,對數據的維護、訪問、存儲cluster index必須是可用的。cluster index用于指向包含給定關鍵字值的rows的block位置。與普通index不同的是cluster indexes會存儲null 值。對于每個cluster index中的關鍵字,只有一條記錄。所以一個cluster index會比普通index的占用空間小。
②hash clusters:它使用hash算法(也已user定義,也可系統指定)計算row的位置。用于查詢和DML操作。對于等值查找clusters key,hash cluster的性能要比index cluster的好。
不應使用clusters的情況:經常執行全表掃描的情況;如果對于所有rows的cluster key的數據超出了一到兩個Oracle blocks,這樣,為了訪問在clustered key table中的一條row,Oracle server需要讀取有相同值的所有blocks。
不應使用hash clusters的情況:如果表不斷增長,并且重建新的、更大的hash cluster不可能的情況下,不應使用hash cluster;如果application經常使用full scans,并且要考慮為table的增大所必須預留的空間。
2)B-Tree indexes:
①使用B-Tree index的情況:當經常訪問表中的記錄占全表的不足5%時,應該考慮創建B-Tree index;如果在查詢時,indexes可以包含所有要訪問的字段,這個百分比可以更高些;或是對可以用于進行表的join時,也應考慮建立B- Tree index。
②indexes的增長方式:index總是平衡的,總是自下而上的增長。當rows被增加時,會添加到葉子節點的block上,如果葉子節點的 block被填滿,Oracle server會將該block split成兩個葉子blocks,每個保存50%的數據。因為新block的添加,葉子節點的父節點也需要添加相應的blocks索引值。如果父節點的 block被填滿,父節點也會被split成兩個節點,類似與剛才的子節點的split。這個過程會循環進行,直到b-tree保持平衡。index的層 次越多,其效率越低。此外,對于delete操作,會降低index的效率,特別是當有15%的rows被刪除,應該考慮rebuilding index。
③為了提高b-tree index的性能,應該定期對index進行rebuild。自9i,可以online創建、rebuild indexes,并且可以并行化進行。當index被rebuild時,相關的table仍然可以被訪問和進程DML操作。
ALTER INDEX i_name REBUILD ONLINE;
–ONLINE關鍵字表示在rebuild時,DML仍可進行。但是不允許并發的DML操作。
④壓縮索引:
在創建索引時使用下面的方法可以對index進程壓縮:
create index i_name on t_name(col1, col2) compress;
重建索引時可以使用:
alter index i_name rebuild compress;
壓縮索引不會多次存儲重復出現的關鍵字從而減少了存儲空間的需求。
對于非唯一索引的壓縮:Oracle存儲重復的關鍵字作為前綴在index block中,唯一的row id作為后綴存儲。
對于唯一索引的壓縮:也是類似的,將一致的前綴只保存一次,用于區分唯一性的部分會作為后綴存儲。但是這只適用于有多個字段組成的唯一索引,如果只有一個column的唯一索引沒有用于share的部分。
3)位圖(bitmap)索引:主要適用于distinct的values很少的字段,在其上建立索引。例如性別、工種等字段。但是對于有大量DML操作的表,bitmap index的性能不好,此情況應慎用。
① 適用bitmap index的情況:對于基數較低(low-cardinality)的column創建的索引;如果查詢語句中使用多個where條件,Oracle server可以使用邏輯的bit-and或bit-or操作來合并不同columns的bitmaps。
②性能的考慮:bitmap index占用空間較小,每個distinct key的存儲時以壓縮的方式,bitmap被分成不同的bitmap segments;對于low-cardinality字段非常快;很適合與規模大的只讀系統,如決策支持系統(DSS);但是對于DML操作性能比較 慢,不適用于OLTP應用,locking是加載在bitmap-segment上的,不是在記錄上的;bitmap index是存儲null值的,但b-tree不存儲;并發查詢、并發DML和并發的CREATE語句在bitmap indexes上是有效的。
③bitmap indexes的創建及管理:
create bitmap index i_name on t_name(col1) storage ( initial 200k next 200k pctincrease 0 maxextents 50) tablespace tsp_name;
對于每個DML操作之后,會對bitmap indexes進行相應的維護,所以對于每個DML操作,每個bitmap segment只會更新一次,既是該bitmap segment中不只一行更新數據。
4)反轉關鍵字索引(reverse key index):在創建索引時會將索引字段按bytes進行反轉(reverse)隨后將結果作為索引關鍵字。
①對于一個不斷增長的關鍵字,如由sequence產生的id,可以通過使用reverse key index避免索引的不斷split。但是對于常使用范圍查找的應用,只能使用全表掃描。
②創建reverse key index:
create index i_name on t_name(col1) reverse pctfree 30 storage( intial 200k next 200k pctincrease 0 maxextents 50) tablespace i_tspname;
或者
create index i_name on t_name(col1);
alter index i_name rebuild reverse;
5)組織索引表(IOT——index-organized table):類似與mysql中的innodb的存儲結構,具體結構如下圖:
適用于頻繁通過primary key或primary key的前綴訪問數據的情況。但是必須要求有primary key的限制。它加快了通過key查找數據的速度,并且從table和index整體上節省空間。
①在IOT中,沒有常規表中的那種物理上的row id的概念,而是引入了邏輯row id的概念,它是以變長的方式存儲的,其size要依靠primary key的值。
對于IOT中數據的訪問有兩種方法:
i)物理猜測guess,訪問時間等同于物理rowid的訪問時間
ii)當guess失敗,則通過primary key訪問IOT中的數據
(guess就是基于row所在的文件和block訪問,block的地址在表建立時是精確的,但是如果leaf block進行了拆分split是,就發生了改變。如果guess失敗,則通過primary key進行訪問。)這里沒太搞懂啊:(
②創建
CREATE TABLE countries
( country_id CHAR(2) CONSTRAINT country_id_nn NOT NULL,
country_name VARCHAR2(40),
currency_name VARCHAR2(25),
currency_symbol VARCHAR2(3),
map BLOB,
flag BLOB,
CONSTRAINT country_c_id_pk PRIMARY KEY (country_id))
ORGANIZATION INDEX
PCTTHRESHOLD 20
OVERFLOW TABLESPACE USERS;
影響IOT的行溢出的三個主要因素有:
** pctthreshold:此子句指明了在index block中容納一行數據可使用塊空間的百分比。如果one row數據超過基于此值計算的大小,所有的在including子句之后的字段將被移入overflow segment。如果overflow沒有被定義,則這種row溢出轉移將被拒絕。PCTTHRESHOLD默認值是50必須在0到50之間。
** including:后跟一個字段,如果數據行的長度超過了PCTTHRESHOLD指定的可用空間,從這個字段之后將數據行分為兩段,后面的部分放入溢出段中;
** overflow TABLESPACE :指明當index-organized表數據超出pctthreshold時,將部分columns放入data segment。
③IOT的字典視圖:
④使用mapping table
create table countries
( country_id char(2) constaint country_id_nn not null,
country_name varchar2(40),
currency_name varchar2(25),
currency_symbol varchar2(3),
constraint country_c_id_pk primary key (country_id))
organization index mapping table tablespace users;
當在索引組織表上創建位圖索引同heap table上創建bitmap是類似的,只是在組織索引表中的rowid對應的不是基礎表,而是相應的映射表(mapping table)。mapping table主要是維護一個邏輯row id(訪問組織索引表所需的)到physical row id(訪問位圖索引所需的)的映射。每個組織索引表會有一個mapping table,用于全表的映射。在heap organized base table中,用key訪問數據時,如果找到相應的key,bitmap記錄返回的是物理row id,可以用于基礎表的訪問。在組織索引表中,位圖索引也是用key進行搜索,當找到相應的key,bitmap返回的依然是物理row id,通過查詢mapping table,獲得相應的邏輯row id,再用于進入guess data block address或是用primary key訪問組織索引表
組織索引表中的row發生移動,不會使其上的bitmap indexes不可用,只是使mapping table中的相應邏輯row id不可用,但仍可通過primary key對其進行訪問。
對于mapping table的維護:
** 通過對IOT表進行analyze獲得mapping table的統計信息
** 查詢DBA_INDEXES視圖得知當前mapping table的精確度
SELECT INDEX_NAME, PCT_DIRECT_ACCESS FROM DBA_INDEXES WHERE PCT_DIRECT_ACCESS IS NOT NULL;
** 如果需要,使用alter table重建mapping table
alter table t_name mapping table update block references;
6)物化視圖(Materialized views)
物化視圖既存儲視圖的定義,又存儲視圖創建語句的查詢結果。可以將物化視圖定義的結果會產生一個實際的表,可以對其做類似normal table的定義,將其指派的某個表空間,對其添加索引,進行分區等。如果通過固化視圖就可以滿足的查詢,server會將查詢轉換為對物化視圖的查詢, 而不是對基礎表的查詢。這樣,部分代價昂貴的如join或統計的查詢就不必重復執行。
①創建:
create materialized view depart_sal_sum
tablespace data parallel (degree 4)
build immediate|deferred refresh fast
enable|disable query rewrite
as
select d.departmet_name, sum(e.salary) from departments d, employees e
where d.departmant_id=e.department_id group by d.department_name;
②refresh 物化視圖:具體有兩類:
i)完全的refresh:主要是通過truncate 當前的data,通過執行物化視圖的創建語句重新插入數據。
ii)fast refresh方法:它只會更新自上次refresh之后發生變化的數據。具體又有兩種:
** 使用materialized view logs:此方法中,所有關于視圖的基礎表的變化都會被捕獲并記錄到一個log中,將這些log data用于materialized view即可。
** 使用row id范圍:此方法需要一個直接裝在日志。記錄了需要被重新load的row id相關信息。materialized view就利用這些row id進行直接路徑的load。
一個視圖的定義使用force的refresh類型時,會盡可能的使用fast refresh方法,不得已才會使用complete refresh。默認情況是使用force refresh類型。如果使用never選項,則會抑制所有materialized view的refresh。
③自動refresh可以通過下面方法設置:
** 如果為materialized view設置oncommit選項,視圖會在base table每次commit操作后進行refresh。因為操作時異步的,所以不會讓user察覺到性能的降低。
** 在具體的時間點:可以使用START WITH和NEXT子句定義每次refresh的具體時間。為了實現此方法,必須將參數JOB_QUEUE_PROCESSES設置為大于0的值。
④可以用DBMS_MVIEW包進行手動的refresh。
** 對具體的某個materialized view進行refresh
DBMS_MVIEW.REFRESH(…)
** 對依賴某個基礎表的所有物化視圖進行refresh
DBMS_MVIEW.REFRESH_DEPENDENT(…)
** 對所有的materialized view進行refresh
DBMS_MVIEW.REFRESH_ALL_MVIEWS;
為了執行手動refresh job,必須為其設置適當的JOB_QUEUE_PROCESSES和JOB_QUEUE_INTERVAL參數。
⑤物化視圖的查詢重寫(query rewrite):這一過程是通過優化器(optimizer)完成的,對于應用而言是透明的。可以加速對基礎表的部分訪問。user不需要被明確的賦予 materialized view的權限,只要其有base table的權限,則其發出的相關查詢就可以被重寫為對物化視圖的訪問。materialized view也可設置為enable和disable。
進行query rewrite,必須使QUERY_REWRITE_ENABLED設置為true。對于使用query rewrite的user必須有GLOBAL QUERY REWRITE或QUERY REWRITE的權限。后者只允許user對自己schema下面的materialized view進行query rewrite,前者除此還可對其他有權限的schema進行query rewrite。
⑥物化視圖在帶來效率的同時也會增加占用的額外空間,并且需要refresh的開支。對此在DBMS_OLAP包的sumary advisor可以用于對代價與收益的比較從而輔助覺得materialized view的創建。
vii)對query rewrit的控制分為三個層次:
** 在初始化參數級別上:
OPTIMIZER_MODE:查詢重寫只有在cost-based優化模式下才能進行。可在session級別動態設置;
QUERY_REWRITE_ENABLED:可設置為true或是false,可在session級別動態設置;
QUERY_REWRITE_INTEGRITY:可設置為ENFORCED(默認值,只有server能確保一致性時——物化視圖是最新的并且 query rewrite使用了有效的驗證約束的情況下才進行query rewrite)、TRUSTED(物化視圖是最新的,此外相信RELY的約束, 就算這個約束沒有Enabled和Validated)、 STALE_TOLERATED(query rewrite允許使用沒有及時refresh的物化視圖)。此參數也是可以在session級別上動態設置的。
** 在sql中使用hints——REWRITE和NOREWRITE,它可以覆蓋在創建或alter物化視圖是設置的enable query rewrite子句。
** dimensions(這個也沒太懂~~~~(>_<)~~~~ )
viii)可以使用dbms_mview包中的EXPLAIN_MVIEW和explain_rewrite對materialized view和query rewrite進行解釋。
3、OLTP系統:
主要特點是:集中的insert和update操作,數據不斷增長,多事務并發進行。要求高可用性、高速、高度并發、降低恢復時間。
1)空間分配:避免動態的空間分配,應該為tables、cluster、indexes明確指明占用的tablespace。此外通過觀察數據增長的規律,設計extent每次分配的大小。
2)indexes:在DB中indexes的創建和維護都是占用一定開支的,所以,索引的創建必須嚴謹,每個索引的存在必須是實際需要的;在外鍵上建立 索引有助于在子表數據被修改時不會locking父表中的數據;b-tree索引在OLTP中優于位圖索引,因為locking對DML的影響(當DML 操作發生時b-tree索引中只是鎖某些rows,但bitmap索引,會locking整個有相同key的rows);可以考慮使用reverse index來解決b-tree中sequence columns的問題;應該定期對indexes進行rebuild。
3)hash clustering:使用hash clusters可以提高等值查詢的訪問速度。但是對于下面的情況則不適用它:
** 大量insert操作
** 存在大量用更大的columns values對表進行update的操作,因為會引起數據的遷移。
如果表不斷增長,可能在hash key上存在大量沖突,從而是部分數據存放在overflow blocks中,為了避免這種情況,正確的評估hashkeys的值。給hash key更大的number,有助于解決沖突。
4)OLTP Application Issues:
* 對于完整性約束,應該使用DB中聲明的constraints代替application中code的邏輯限制。這里主要考慮的是參照完整性和約束的check。
* 應該考慮使用Oracle中的共享code對象,如packages、procedures和Functions。
* 應該盡可能使用綁定變量
* 定義恰當的cursor_sharing參數,有助于user共享解析代碼。可設置的值有:
EXACT:默認值,只在精確匹配的情況下共享cursors
SIMILAR:如果SQL語句是字面量,則只有當已有的執行計劃是最佳時才使用它,如果已有執行計劃不是最佳則重新對這個SQL語句進行分析來制定最佳執行計劃。
FORCE:如果SQL語句是字面量,則迫使Optimizer始終使用已有的執行計劃,無論已有的執行計劃是不是最佳的。
4、決策支持系統(DSS/Data Warehouses)
DSS的特點是該application會提取相應的有用數組成容易理解的報表。將OLTP中的數據進行提取、整合、匯總。使用大量的全表掃描。決策者根 據相關的結果做下一步的決策。它需要有快速的響應時間,并且數據應該確保精確。并發查詢的特點就是為了data warehouse環境設計的。
1)存儲的分配:
* 謹慎的考慮block size和DB_FILE_MULTIBLOCK_READ_COUNT參數的設置。可以考慮適當增大block_size、DB_FILE_MULTIBLOCK_READ_COUNT。
* 確保extent的size是block_size的整數倍。
* 定期執行analyze或是dbms_stats進行表的statistics。
2)indexing:因為大量的查詢是通過全表掃描完成的,所以應盡量減少index占用的空間和對其維護帶來的開銷。
* 可以的話,可以考慮不使用索引,只保留那些需要用于進行篩選查詢的index;
* 定期的用不一致的分布數據產生直方圖。
* 考慮使用bitmap indexes
* 對于需要快速用關鍵字查詢的data可將相應的表建為IOT。
* 考慮使用index和hash cluster,特別是hash cluster。但不要在定期批量增長的表上建立cluster。
3)application issues:
在data warehouse中,sql的解析時間并不重要,所以可以適當的減小library cache的大小。應該更關注執行計劃:盡量使用并發查詢。Symmetric multiprocessors (SMP), clustered, or massively parallel processing (MPP)將能很好的提高性能。SQL的調節優化很重要。
有時可以棄用綁定變量,因為:當analyze后產生直方圖,可以用于一定的查詢優化,但是這種優化只使用在不使用綁定變量的情況。如果使用綁定變量,則optimizer就不會使用直方圖了。對此要小心設置cursor_sharing參數的值。
5、混合系統(Hybrid System)
1、對于閂(Latches)的概覽
Latches是為了保護SGA中的共享數據結構而創建的簡單的底層的序列化機制,是輕量級的鎖。server或后臺進程為了操作或是查看共享數據結構必 須先申請Latches,當操作結束,需要釋放Latches。Latches的爭用是不用tuning的,它是不合理使用SGA資源的征兆,需要 tuning內部的爭用。僅僅是觀察v$LATCH是不足的,但可以將其看做是診斷工具,查找SGA資源爭用的位置。
1)Latches的目的:
* 控制序列化訪問:保護SGA中的數據結構;保護共享內存的分配。
* 序列化執行某些操作:避免同時執行某些關鍵的臨界code;避免corruptions。
2)等待Latch
盡管latch的實現根據不同的OS和平臺而不同,但是其都是內存中的一塊地址空間,當latch空閑時是0,已經被申請了時為非0值。
在單cpu中,當進程p1申請的latch被占用,p1將釋放cpu,sleep一小段時間,等待latch被釋放。
在多cpu中,如果進程p1申請的latch被p2占用,很可能p2在其他的cpu上,則p1不會釋放cpu,而是spin計數,重試,spin計數,重試,直到重試次數達到設置數,仍未成功,才會釋放cpu,但這種可能比較小。
3)Latch的請求類型:
latch的請求方式有兩類:willing-to-wait和immediate。
willing-to-wait:當進程申請一個latch時,如果當前latch已經被占用,該進程會等待片刻再重試,等待-重試,直到獲得latch,這是一般普遍的latch申請方式。
immediate:如果進程申請的latch不能獲得,該進程會繼續執行后續的指令。
4)latch 沖突:latch的申請釋放都是Oracle自動實現的,所以速度比較快。latch的資源是有限的。
在診斷latch時,可利用視圖v$latch,該視圖中主要columns的意義:
• gets: Number of successful willing-to-wait requests for a latch
• misses: Number of times an initial willing-to-wait request was unsuccessful
• sleeps: Number of times a process waited after an initial willing-to-wait request
• wait_time: Number of milliseconds waited after willing-to-wait request
• cwait_time: A measure of the cumulative wait time including the time spent spinning and sleeping, the overhead of context switches due to OS time slicing and page faults and interrupts
• spin_gets: Gets that missed first try but succeeded after spinning
• immediate_gets: Number of successful immediate requests for each latch.
• immediate_misses: Number of unsuccessful immediate requests for each latch.
在使用statspack是,可先查看其report的top 5 wait events部分,是否有latch free事件,如果有再進行后續的分析。
2、降低Latches的沖突
一般,DBA不應該調節latches的數目,自9i以來,Oracle已經可以自己進行latches數量的調節了,這主要是根據DB在建立時設置的初始參數和OS的環境。
latches的沖突是性能問題的表現。最好的解決latches沖突問題的方法是修改application行為。此外,如果觀察到是buffer或shared poolsize的問題,也需要進行適當的修改。
3、對DBA而言,幾個重要的latches
1)shared pool latch和library cache latch:如果沖突出現在這兩類latch上,則表示sql或是pl/sql命令沒有被有效重用,可能是沒有有效的使用綁定變量,或是cursor cache不足。如果是Oracle Shared server模式,如果沒有設置large pool,也可能導致Shared pool Latch的沖突,則需要考慮設置large pool。
2)cache buffer lru chain latch:當dirty blocks被寫入disk或server進程查找blocks用于寫入操作時會request此latch。如果它存在較大沖突,則表示buffer cache任務繁重,可能存在較多的cache-based sorts、低效的SQL(使用了不正確的迭代索引)或是較多的全表掃描。此外,也可能是由于DBWn的寫速度跟不上data blocks的變化速度。使得訪問進程不得不為了找到buffer中的free blocks等待。對這個latch的沖突,應該從buffer cache或DBWn的調節入手。
3)cache buffers chains latch:當user進程試圖分配buffer cache中的data blocks時,需要申請此latch。它的沖突反映了某些熱塊被重復訪問的情況。
4、共享池和library cache latch沖突:如上所述,此類沖突的一個主要原因是不必要的解析。其調節方法已經在之前介紹過了。
1)辨識因為拼寫方式而造成的多次解析:
select sql_text from v$sqlarea where executions=1 order by upper(sql_text);
2)查看是否有不必要的重復解析。
select sql_text, parse_calls, executions from v$sqlarea order by parse_calls;
1、rollback segments的作用:事務的rollback;transaction recovery(當事務尚未提交或rollback時instance fail,startup時會用rollback segment進行回滾恢復);讀一致性也需要rollback segment進行數據的還原。在新的版本中(我記得是從10g中)flashback技術也使用了rollback segment。這里先不介紹了,碰到時在說。
2、rollback segment的activity:
1)transaction以順序循環的方式使用rollback segment中的extents。一個transaction在rollback segment的當前位置寫入記錄,并將指針移動寫入記錄的大小的步長。寫入rollback segment的請求需要相應的undo data在database buffer cache中是可用的。這就要求有較大的buffer cache。
2)注意:多個transaction可以對一個rollback segment中的同一個extent進行寫操作。每個rollback segment block只會包含一個transaction的數據信息。
3)rollback segment header中包含了不同transaction各自的記錄:Oracle server在每個rollback segment header中保存一個transaction tables,從而控制改變rollback segments中data block的操作。
因為需要不斷修改,所以rollback segment header block被長期保存在data block buffer cache。而不斷的訪問rollback segment header block會增加命中率。這種影響對于某些有大量小型事務的OLTP的application影響較大。每個transaction都需要修改 transaction tables,所以必須有足夠大的rollback segment從而避免對transaction tables的沖突。低估rollback segment的需求,可能引起性能問題或errors。高估會浪費空間。可以使用自動undo表空間管理的方法管理undo segments。
4)rollback segments的增長:
當當前extent寫滿后,指針或是rollback segment的頭回移動到下一個extent。當最后一個extent作為當前寫入的extent,被寫滿后,如果此時第一個extent是free 的,則指針將指向第一個extent的開始。指針式不能跳過(skip over)extent,移動到后面的extent上的。所以如果第一個extent仍被使用,將會為此rollback segment分配一個新的extent。這被稱作extend。
在正常的運行期間,rollback segments不應該被extend。所以在之前應該分配足夠的rollback segment空間。應該盡量避免動態空間的管理。
2、調節手動管理的rollback segments
1)調節rollback segment的目標:
* 盡量使transaction不會為訪問rollback segment而等待:這需要有足夠的rollback segment
* 在運行期間,應避免rollback segment的extend:
需要每個segment有適當數量的extents
extents的四則應該正確
適當數量的rollback segment
盡量減少應用中對rollback的應用
* 應該沒有transaction把rollback space占用完:對此應該將較大transaction用多個transaction替代
* 數據查詢user應該總是能獲得讀一致的數據:這需要考慮設置適當數量的segments和適當的segments size。
2)診斷工具:常用的監控視圖有:
* V$ROLLNAME:顯示了在線rollback segments的名字和數量
* V$ROLLSTAT:顯示了每個在線rollback segment的統計信息。等待header transaction tables的數量,transaction寫數據的卷標等信息。
* V$WAITSTAT:顯示等待header blocks和rollback segments的blocks累計數量。undo header和undo block兩條記錄。
* V$SYSSTAT:顯示
select name, value from v$sysstat where name like ‘%undo%’;
* V$TRANSACTION:顯示當前transaction使用的rollback segment和require的空間的卷標。
在查詢時需要用視圖中的USN作為連接字段。
3)對手動管理的rollback segment header沖突的診斷
查看:v$rollstat中的waits字段;v$waitstat中的undo header行;
select event, total_waits, time_waited from v$system_event where event like ‘%undo%’;
select class, count from v$waitstat where class like ‘%undo%’;
select sum(value) from v$sysstat where name in (‘db block gets’, ‘consistent gets’);
select sum(waits)*100/sum(gets) “ratio”, sum(waits) “waits”, sum(gets) “gets” from v$rollstat;
當等待的比率大于1%,則考慮創建更多的rollback segment。
4)對于手動管理的rollback segment的數量的考慮
* 對于OLTP application,其特點是有大量的小transaction并發,每個transaction只修改很少的數據量。對此可以設置small rollback segments。一般的設定規律是,并發的transaction中,每4個設置一個rollback segment。
* 如果對于存在較大的批量transaction時,如果rollback segment較小,就可能會發生extend。允許rollback segment可以無限自行extend。
* 如果想要給long transaction分配large rollback segment,可以使用下面的語法:
SET TRANSACTION USE ROLLBACK SEGMENT large_rbs; –必須是事務的第一句
或
execute dbms_transaction.use_rollback_segment(‘large_rbs’);
5)Sizing 手動管理的rollback segment的大小
設置適當的rollback segment size一方面可以避免動態的extend,另一方面當undo blocks被請求時增大了它在cache的可能性。
* 對于small transactions設置segments的initial參數為8KB、16KB、32KB或64KB,對于larger transaction設置為128KB、256KB、512KB、1MB、2MB、4MB等。該值應該設置的足夠大,以免出現wrapping現象(當 一個rollback entry在當前使用的空間中找不到足夠的空間時,被寫入下一個extent)。
* 使用與initial相等的數值做next的參數值。因為PCTINCREASE設置為0,所以后續所有的extents都將是next大小。
* 將DB中的所有rollback segment都設置為相同的size。如果暫時不需要large rollback segment,可以先將其offline。
* 將minextents參數設置為20 。這大致可以避免extend的現象。
* 對于表空間的size設置,我以為書中沒有介紹太多的方法,需要在實際應用中查看產生的undo entries的數量進行設置。此外,可以為其保留一個專門用于large-than-usual transaction的segment。
3、transaction rollback data的sizing
1)不同的sql操作所產生的rollback data的大小有下面而定:
* delete操作對rollback segment的開銷很大,會存儲實際row的數據。如果使用truncate,則會對性能有所改變,但是因為沒有寫rollback entries,所以不能再恢復。
* insert 使用的rollback space很少,只會記錄row id。
* update操作占用的空間要依靠修改的字段數量而定。
* indexed 值將會產生較多rollback。因為server在修改index的同時需要修改tables中row,對于對index字段的update操作,需要 記錄old data value、old index value和new index value。
note:lob數據類型的回滾數據不使用rollback segment space,而是占用其自己的segment中由參數pctversion定義的大小的空間。
可以通過下面的sql查看當前事務產生的rollback data
select s.username, t.user_ublk, t.start_time from v$transaction t, v$session s where t.addr, s.taddr;
2)另一種衡量方法是,實際執行相應的操作,從而觀察rollback segment的變化
* 在執行操作前運行:select usn, writes from v$rollstat;
* 執行測試的事務操作
* 再次查看rollback segment的統計數據:select usn, writes from v$rollstat;
4、使用產生少量rollback data 的語句:
* user應該盡可能有規律的commit,避免其transaction鎖住外部的rollback segment extents。
* 開發人員應該在code時不使用long transaction。
* import操作時,指定commit=y,使得每插入一定數據后就進行commit;用buffer_size關鍵字設置rows集合的大小。
* export操作時:設置參數consistent=n,避免該是我被設置為只讀,那將占用更多的rollback segment space。consistent=y時,確保了導出的數據在一個時間點上是一致的。
* sql*loader:在執行時也應用rows關鍵字設置commit interval。
note:對于小rollback segments可能帶來的問題有:
* interested transaction list(ITL)被存放在block的header。每個ITL entry都包含了發起此處變更的transaction id、undo block的位置、標識位、空閑空間credit和SCN。row lock byte包含了ITL實體number,就相當于該transaction擁有該row的鎖。
如果transaction很大,可能會由于rollback segment達到其最大的extents,或是表空間中已經沒有可用于extend的空間給rollback segment了,而導致transaction的失敗。
* 在查詢操作遇到ORA-01555: snapshot too old (rollback segment too small)的錯誤時,說明此操作需要為了保持一致讀的鏡像數據塊被其他transaction覆蓋了。對此的修復只有增大rollback segments。
5、自動管理undo表空間模式
從9i開始,也已通過將UNDO_MANAGEMENT設置為auto將DB設置為自動管理undo表空間的模式(AUM),如果設置為manual則仍 使用手工的管理(RBU)。當在一個transaction中,第一個DML操作被執行,transaction將被分配到當前undo tablespace中的一個rollback segment上。可以通過參數UNDO_RETENTION設置存放在AUM中的undo信息的數量。
1)AUM的tablespace:
具體創建undo tablespace的方法:create database是使用undo tablespace子句,此時會創建一個名為SYS_UNDOTBS的undo tablespace,在$ORACLE_HOME/dbs下將會生成DBU1<SID>.dbf的文件,并且autoextend=on; 另外可以使用create undo tablespace創建。
2)對于AUM的表空間,可做下面的操作:
alter tablespace tspname
• ADD DATAFILE
• RENAME
• DATAFILE [ONLINE|OFFLINE]
• BEGIN BACKUP
• ENDBACKUP
DBA仍可切換當前使用的undo tablespace,只有一個undo tablespace可以設置為active。
eg:ALTER SYSTEM SET UNDO_TABLESPACE=UNDOTBS2;
當該指令發出,所有新的transaction將被指向新的undo tablespace,當前正在運行的transaction將繼續沿用舊的undo tablespace,直到結束。
DBA只能通過drop tablespace命令刪除當前非active的undo tablespace,并且其不包含任何未提交的transaction的rollback data。
3)對于自動管理undo tablespace的參數設置:
* UNDO_MANAGEMENT:指明是AUTO或MANUAL
* UNDO_TABLESPACE:指明當前active的undo tablespace。如果在創建是沒有undo tablespace可用,則會使用system表空間作為rollback segment的分配空間。
* UNDO_SUPPRESS_ERRORS:此參數主要用于使用SET TRANSACTION USE ROLLBACK命令下
* UNDO_RETENTION:設置存放在AUM中的undo信息的數量。其單位是秒,默認值是900
關于undo retention所需的空間的計算:
undo space = (UNDO_RETENTION * (undo blocks per second*db_block_size) ) + DB_BLOCK_SIZE
可以使用下面的sql進行計算,并設置undo tablespace的大小:
SELECT (RD*(UPS*OVERHEAD) + OVERHEAD) AS “bytes”
FROM (SELECT value AS RD FROM v$parameter where name = ‘undo_retention’),
(SELECT (SUM(UNDOBLKS)/SUM(((end_time-begin_time)*86400))) as UPS FORM v$undostat),
(SELECT value AS Overhead FROM v$parameter where name=’db_block_size’);
4)對自動管理undo tablespace的監控:
通過查看V$UNDOSTAT視圖可以完成監控的任務。字段UNDOBLKS顯示了undo blocks的分配數量。
1、Locking機制
1)Oracle Server中是自動管理鎖的。默認會使用最低的鎖級別對數據進行一致性的保護,從而滿足最大的并發度。
note:默認的鎖機制可以通過ROW_LOCKING改變。默認該值是ALWAYS,它將在DML語句中使用最低級別的鎖。另一個可能的值是 INTENT,它將使用更高級別的限制(table level),除了select for update語句,它將使用行級鎖。
2)quiesced database:如果Oracle被設置為只有DBA可以訪問的狀態時,就是quiesced database。
3)鎖的種類:
** DML locks:
①表級鎖(TM):當修改table data時,被設置,如:INSERT, UPDATE, DELETE, SELECT … FOR UPDATE或LOCK TABLE。此時table將被加鎖,避免其他DDL的操作引起transaction之間的沖突。
## 在TM中又可分為兩種鎖,是由server根據當前其他表鎖的加載情況而自動為DML選擇加上的。這兩種鎖具體是:row exclusive(RX),運行其他transaction中的insert、update、delete或其他加行級鎖的并發操作在當前同一 table上,但不允許其他手動加載的排他讀/寫鎖;row share(RS),運行SELECT … FOR UPDATE命令時加載的表鎖,這只會對避免其他事務手動的對當前table加載鎖用于排他的寫操作。
## 表鎖模式:
(i)手動加載表鎖模式使用語句LOCK TABLE table_name IN mode_name MODE; –一般不使用這種明確加鎖的方法,只有application要求,才會不得不加較高級別的鎖。
(ii)Share(S)鎖模式:此類表鎖只允許其他transaction發出select … from update的請求,不允許任何對table的修改。隱含式的獲得share lock的sql語句中,會包含相應的完整性約束。在9i中,不會申請子表中外鍵字段的索引約束。
(iii)Share Row Exclusive(SRX):它是比S模式更高的鎖模式。它不允許任何其他的DML語句和手動加載的共享鎖模式。相應的SQL語句會隱式的獲得相應的完整性約束的SRX鎖。
(iv)Exclusive(X)鎖:這是最高的鎖模式,只允許其他對該表的查詢請求,拒絕一切對表的任何DML操作和手動鎖。
②行級鎖(TX):當發出命令INSERT, UPDATE, DELETE, SELECT … FOR UPDATE命令時,會自動為所操作的row對象加TX,從而確保沒有其他user同時對同一行進行才操作。
一個DML事務,會同時獲得兩個鎖:共享表級鎖和排他行級鎖。獲得行級鎖的每行都返回
③在blocks中的DML鎖:加鎖的信息只有在transaction被commit或是rollback后才會被清除。而不是在當前事務的下一個請求語句發起時被釋放。在blocks header中,Oracle server為每個當前active的transaction保存了一個標識符。在每條row中,會有一個lock byte存儲了包含當前transaction的slot的標識符。
** DDL locks:避免對schema對象的定義時,有其他相關的DDL操作進行。
Oracle是通過入隊的方式對鎖進行維護的,入隊機制會記錄下面的信息:user等待的locks被其他user占用;users請求的locks的具體類型;users請求的locks的順序。
可以通過改變參數DML_LOCKS和ENQUEUE_RESOURCES參數來增加可被request的locks。這在Parallel server中是必須的設置。DDL鎖的分類有:
①Exclusive DDL Locks:某些DDL語句,如CREATE, ALTER, DROP,必須獲得其操作object的排他鎖。如果其他user獲得了其他任何級別的lock,當前user都不能得到其DDL的排他鎖。
②Shared DDL locks:當發起GRANT和CREATE PACKAGE操作時,需要獲得相應object的共享DDL lock。該類locks不會阻止類似的DDL語句或是任何DML語句,但會防止其他user對當前引用的object被修改或刪除。
③Breakable Parse Locks:保存在library cache中的statement和PL/SQL對象保存了其引用的每個object的breakable parse Lock,直到該statement過期。它用于檢驗library cache中的相應內容是否因為object的改變而可用。
2、可能引起Locks沖突的原因:
1)使用了不必要的high-level鎖
2)長期運行的transaction的存在
3)user沒有及時的commit對database的修改
4)使用Oracle instance的application使用了higher locks
3、監控并診斷當前加鎖情況的工具
1)如上圖所示,其中視圖DBA_WAITERS和DBA_BLOCKERS用于進一步查看當前獲得或是等待不同table的locks的信息。對此,需要用$ORACLE_HOME/rdbms/admin中的catblock.sql腳本創建。
2)對于v$lock視圖來說,當lock tpye為TX時,id1中顯示的回滾段的number和slot number;當lock tpye為TM時,id1中顯示的是被修改表的object ID。
SELECT owner, object_id, object_name, object_type, v$lock.type FROM dba_objects, v$lock WHERE object_id=v$lock.id1 and object_name=table_name;
3)V$LOCKED_OBJECT視圖
XIDUSN:Rollback segment number
OBJECT_ID:ID of the object being modified
SESSION_ID:ID of the session locking the object
ORACLE_USERNAME
LOCKED_MODE
在此視圖中,當XIDUSN為0時,則表示當前session正在等他其他已經獲得該lock的session釋放。
4)關于腳本utllockt.sql
可以使用$ORACLE_HOME/rdbms/admin/utllockt.sql腳本顯示當前等待lock的進程繼承關系。但使用之前必須用catblock.sql腳本創建視圖dba_locks和dba_blockers。
5)如果想要得知哪一行造成了lock沖突,可以查看v$session中的row_wait_block#, row_wait_row#, row_wait_file#, row_wait_obj#四個字的的值。
4、解決locks的沖突方法有:一方面可以請相應的user做commit/rollback;在萬不得已的時候,可以kill掉某些user session,從而回滾相應的transaction并釋放locks。具體方法如下:
select sid, serial#, username from v$session where type=’USER’;
alter system kill session ’sid,serial#’;
5、死鎖:對于Oracle,當其檢測到死鎖的存在,會rolling back那個檢測到死鎖的語句,當不是整個transaction的rollback。必要時,需要DBA完成剩下的rollback工作。明確的指明語 句中使用的鎖,從而覆蓋默認的鎖機制,可能容易引起deadlock。
當發生死鎖后,server會將deadlock的情況記錄到USER_DUMP_DEST目錄下的跟蹤文件。在分布式transaction中,本地的 deadlock是通過等待關系圖(waits for graph)來判斷的,全局死鎖是通過time-out來判斷的。
Oracle進程與files
1、performance guidelines
1)對于吞吐量較大的OLTP應用中,當使用dictionary管理表空間的方法時,由于所有的extent分配時都會要訪問dictionary,從而造成了沖突。而使用本地管理表空間的方法避免了這類沖突,從而提高了并發性。
2)在本地管理表空間中,使用自動空間管理方法,用位圖記錄不同blocks的使用情況。也提高了相應的速度。
3)當創建一個user后,就會分配一塊所需的磁盤排序所需臨時表空間。這些排序區應該從其他database object中分離開,如果沒有給user分配臨時表空間,則其所需的排序區域將從system表空間分配。
4)tables和indexes應該被分開存儲在不同表空間中。因為indexes和tables經常被同時讀寫。
5)對于含有LONG或LOB數據類型的tables,應該被分配在不同的表空間中。
6)適當創建多個臨時表空間。
2、distributing files across devices:
1)應該將redo log和data file存放在不同的磁盤上,從而在一定程度上降低i/o的壓力。
2)對于規模較大的表,如果分不同的區域并發訪問也可以提高性能partition。
3)盡可能排除非Oracle Server進程對database file的I/O操作。對此可以使用v$filestat動態的觀察。
4)了解應用程序主要的I/O操作,合理安排disk布局,從而提高性能。
3、表空間的作用:其中system表空間主要是用于存放sys創建的data dictionary objects。其他users不可使用該表空間。需要明確的是,packages和database triggers對象等都是data dictionary的一部分。rollback segments應該排他使用其rollback segment。undo segments可以只能存在在undo tablespace中。
4、監控I/O狀態的工具
1)v$filestat視圖。
select phyrds, phywrts, d.name from v$datafile d, v$filestat f where d.file# = f.file# order by d.name;
2)statspack
5、file striping
1)對OS的striping,通過使用硬件或是軟件層次上的striping,可以將同一個文件的不同blocks放在不同的devices上,例如raid技術。提供一定的冗余的同時增大I/O性能的。
此外,設置適當的DB_FILE_MULTIBLOCK_READ參數。
2)手工的striping:可以在多個不同的disk創建tablespace。隨后將不同的tables、indexes分配到不同的 tablespace中。此外,可以創建對象時使用MINEXTENTS句柄其值大于1,這樣每個extents都將略小于striped data files。也可直接給extents進行分配定位(但我認為這會給管理帶來麻煩):alter table tablename allocate extent ( datafile ‘filename’ size 10M);
對于這塊爭用的問題,使用手動的striping還是比較有效的。
6、對全表掃描的tuning:當對某個disk有較高的讀寫操作時,多是由于沒有適當調節sql的原因。
查看全表掃描的次數:
select name, value form v$sysstat where name like ‘%table scans%‘;
獲得的結果中’table scans ( long tables)’的值如果較大,則需要考慮調節sql或是增加適當的indexes。
long tables (長表)指多于4個塊的表, short table(短表)指等于或小于4個塊的表。
初始化參數DB_FILE_MULTIBLOCK_READ_COUNT決定了在全表掃描時,一次I/O操作中讀入的最大的database blocks。它可以改變全表掃描時需要的I/O的次數。該參數的設置應該受到OS限制的I/O的上限的約束。此外此參數還可以在session級別進行 調節。對它的調節可以先查看完成每個表的全表掃描掃描多少blocks。從而從整體上得到較好的設置。要注意的是,對cost-based 優化將會使用該參數評估使用全表掃描的代價,從而判斷是否使用全表掃描。
對于全表掃描,Oracle提供了視圖v$session_longops來進行監控。
select sid, serial#, opname, to_char(start_time,’HH24:MI:SS’) as starttime, (sofar/totalwork)*100 as percent_complete from v$session_longops;
7、checkpoints
什么是checkpoint?
checkpoint是一個數據庫事件,它將已修改的數據從高速緩存刷新到磁盤,并更新控制文件和數據文件。
什么時候發生checkpoint?
我們知道了checkpoint會刷新臟數據,但什么時候會發生checkpoint呢?以下幾種情況會觸發checkpoint。
1.當發生日志組切換的時候
2.當符合LOG_CHECKPOINT_TIMEOUT,LOG_CHECKPOINT_INTERVAL,fast_start_io_target,fast_start_mttr_target參數設置的時候
3.當運行ALTER SYSTEM SWITCH LOGFILE的時候
4.當運行ALTER SYSTEM CHECKPOINT的時候
5.當運行alter tablespace XXX begin backup,end backup的時候
6.當運行alter tablespace ,datafile offline的時候;
1)它可以引起DBWn的I/O操作,同時會更新datafile header和control file中的scn等信息。
頻繁的進行checkpoint可以縮短instance恢復的時間,但是會降低Oracle運行的性能。
在LGWR寫redo log文件時,當一個group 被寫滿時,需要進行log switch是,會先發起一個checkpoint,這就意味著:DBWn會先將所有的與該redo log有關的dirty data blocks寫入datafile,隨后CKPT會修改datafile header和控制文件。
checkpoint并不會影響其他工作。如果DBWn進程尚未完成checkpoint一個file,此時LGWR需要在此需要這個file時,LGWR不得不等待。
2)對checkpoint性能的監控與調節:
** checkpoint的監控主要是查看alert.log文件。可以將LOG_CHECKPOINT_TO_ALERT參數設置true,從而記錄checkpoint的開始結束時間。
** 通過調節online redo log files的大小來降低因日志切換引起的checkpoint;
** 增多redo log 的groups,從而延長LGWR覆蓋寫的時間,從而避免引起不必要的LGWR等待。
** 具體可調節的參數有:
– FAST_START_IO_TARGET
– LOG_CHECKPOINT_INTERVAL
– LOG_CHECKPOINT_TIMEOUT
– DB_BLOCK_MAX_DIRTY_TARGET
– FAST_START_MTTR_TARGET
如果在OLTP系統中,SGA設置過大,同時checkpoint稀少,可能引起disk沖突。所以也要適當增加checkpoint的頻率。
貌似我的理解是除了user發起的alter database checkpoint命令外,主要兩類checkpoint,時間間隔型和fast-start類型的。
通過查看v$instance_recovery視圖,查看參數設置對DB recovery時間的影響,其中:
RECOVERY_ESTIMATED_IOS:顯示了基于fast-start的設置,在recovery時,需要處理的data blocks。
ACTUAL_REDO_BLKS:顯示了當前要進行recovery時所需的redo blocks。
TARGET_REDO_BLKS:在recovery時,最大的需要處理的redo blocks。是下面四個指標的最小值。
LOG_FILE_SIZE_REDO_BLKS:在recovery時,為了確保log switch不會等待checkpoint,要處理的redo blocks數量。
LOG_CHKPT_TIMEOUT_REDO_BLKS:在recovery時滿足log_checkpoint_timeout,需要處理的redo blocks的數量。
LOG_CHKPT_INTERVAL_REDO_BLKS:在recovery時為了滿足log_checkpoint_interval,需要處理的redo blocks的數量。
FAST_START_IO_TARGET_REDO_BLKS:在recovery時為了滿足fast_start_io_target,需要處理的redo blocks的數量。
對checkpoint的設置主要圍繞的中心就是recovery用時,和它引起的I/O是否會造成性能的問題。
8、redo log的groups和members的設計
一般會把同一組的不同成員放置在不同的disk上,如果在歸檔模式下,則要考慮將歸檔日志放到不同的磁盤上。為redo log選擇適當的size。同時在一定程度上增加log file的groups,從而避免不必要的等待。
對redo log的監控視圖主要有:V$LOGFILE, V$LOG, V$LOG_HISTORY,此外還可結合v$system_event獲得的結果。
9、歸檔日志的設置
當開啟歸檔模式時,可以考慮將不同的groups放在不同的disks上(當然不一定是每個group一個磁盤),同時與歸檔文件的存放也分離,這樣使LGWR進程寫的disk和ARCn進程讀的disk不在一個上。
可以從視圖V$ARCHIVED_LOG上獲得動態的歸檔log文件的信息。V$ARCHIVE_DEST當前歸檔進程的destinations的狀態信息。(由參數log_archive_dest_n設置的destination)
監控診斷ARCn的工具主要是使用視圖:V$ARCHIVED_LOG, V$ARCHIVE_PROCESSES, V$ARCHIVE_DEST。
對歸檔的調節,可以使用LOG_ARCHIVE_MAX_PROCESSES參數指定最大可以創建的歸檔進程。
如果預計歸檔工作量較大,可以通過定期運行下面語句來獲得其他進程來分擔。
alter system archive log all to ‘directory_name’;
注意:9i中,當DBWR_IO_SLAVES參數的設置大于0,Oracle會自動將ARCn的進程數設置為4。(但是我的11g貌似DBWR_IO_SLAVES=0,而ARCn也是4個多啊,大概是設了其他的參數)
設置適當的fast_start_io_target,
1、排序進程:
1)如果排序請求使用的memory不大于參數SORT_AREA_SIZE的設置值,則sort操作在內存中進程。反之,如果超過該值:
①數據將被分隔成更小的pieces,被稱作sort runs;每個sorted先被分別的sort。
②server進程會將pieces寫入臨時表空間segment中;這些segments用于存儲中間的sort data。
③sorted pieces被合并從而產生最終結果。如果SORT_AREA_SIZE大小不足以一次merge所有sorted runs,sorted runs的子集會經歷幾次merge過程。
2)sort area的大小是由SORT_AREA_SIZE設置的,它可動態設置(alter session、alter system deferred),其默認值根據OS的不同而不同。其默認值可以滿足一般的OLTP需求,對于DSS應用、批量jobs或是較大操作需要適當的條件。
3)另一個相關的參數是SORT_AREA_RETAINED_SIZE。當sorting操作結束,sort area仍保存了部分等待取出的sorted rows,sort area可以shrink到最小為SORT_AREA_RETAINED_SIZE的大小。該部分memory仍然是被釋放到UGA中。其默認值等于 SORT_AREA_SIZE。
4)關于位圖索引的初始化參數:
CREATE_BITMAP_AREA_SIZE:此參數是靜態的,指明了用于創建位圖索引可以分配的memory,默認值是8MB(較大的memory設置會加快bitmap的創建速度,如果位圖索引的基數比較小,所需的memory也相對小)
BITMAP_MERGE_AREA_SIZE:該參數也是靜態的。默認值是1MB。oracle為索引位圖段建立一張位圖。在進行位圖索引掃描時,需要將掃描到的位圖索引排序后與位圖合并(Merge
),Oracle會在PGA中開辟一片區域用于排序和合并。它就指定了這片區域的大小。
5)sort Area的新參數:
PGA_AGGREGATE_TARGET:指明了連接instance的所有進程的PGA的總區域大小,大小可從10MB到4000GB。設置時,應該先考慮system總的memory,以及分配給SGA的memory大小,將剩余的部分分配給該參數。它指明了自動sort area管理。
WORKAREA_SIZE_POLICY:該參數可設置為(i)AUTO:只有定義了PGA_AGGREGATE_TARGET參數后才可被設置為 AUTO;(ii)MANUAL:對work areas的Sizing是手動的,是基于*_AREA_SIZE參數設置的值來分配的。如果設置為MANUAL,可能會降低PGA內存的利用率。
6)一般SORT_AREA_SIZE和SORT_AREA_RETAINED_SIZE應該設為相同的大小,除非system memory不足或使用的是Oracle shared server模式。
7)內存的需求:
在single server process中:一個執行計劃可能會包含多個排序。例如,一個用sort-merge方式join兩個tables并使用order 不用子句的sql,包含了三個sort。對此,在運行order by時,一個SORT_AREA_SIZE大小的memory用于當前的sort;兩個SORT_AREA_RETAINED_SIZE大小的 memory用于join sorts。
在parallel query 進程中:假設有2個server,則會使用(SORT_AREA_SIZE*2*并發度)大小的memory,此外如果需要,還要使用 (SORT_AREA_RETAINED_SIZE*并發度*事先做的排序次數)的memory。實驗表明分配更大的memory不會對性能有更好的提 高。
2、Tuning sorts
需要注意的問題有:
* 如果數據已經使用索引進行了排序,盡量避免再次排序
* 如果sort操作本身并不大,但是設定的sort area過小使得其不得不進行頁面的交換。
* 此外使用大的內存chunks用sort也會造成paging核swapping,從而降低系統性能。
* 避免在頻繁分配和收回磁盤上的臨時表空間操作
所以應該:盡可能的避免排序操作;盡量使sort操作在內存中完成,減少swapping和paging的操作;盡可能的減少對臨時空間的請求。
1)臨時表空間的優化:
明確指明sort操作使用的臨時表空間,可以有效的避免在分配與收回sort空間時的序列化操作。在臨時表空間中,不能包含任何永久的object,在 Oracle Parallel Server中,對于每個instance,會有一個單獨的臨時表空間。臨時表空間的datafile在備份時時不需要備份的。
對于臨時sort segment:
* 在第一次需要申請臨時表空間的sort操作申請時,sort segment才被創建;
* 在DB被關閉時才被drop,可以用命令行對其進行擴容
* 它也是由extents組成的,可以用于不同的sort 操作
* 在SGA中存在一個叫sort extents pool(SEP)的數據結構,用于管理臨時表空間。當進程需要申請sort space時,會先在SEP中查找臨時表空間中空閑的extents。
2)需要進行排序的命令請求有:
* 索引的創建:在建立b-tree之前,必須先將索引列進行排序操作;
* order by和group by子句:必須先對該子句使用的字段進行排序;
* distinct關鍵字:必須為消除重復行先進行排序;
* UNION、INTERSECT或MINUS操作符:server需要為了消除重復rows先對表進行sort。
* 兩表之間的sort-merge連接:如果沒有相應的索引用于兩表的連接,對于等值連接,如果使用此方法join,則先需要對兩表進行全表掃描,并分別進行排序,再合并兩表。
對于server的排序操作的監控,可以從v$sysstat中查看:
select name, value from v$sysstat where name = ’sorts (rows)’;
可以使用analyze或是dbms_utility.analyze_*等方法對tables、indexes或是cluster進程統計,從而更好的指導CBO,從而產生更好的執行計劃。
3)避免使用sort:在任何可能的地方盡量避免使用sort
* 使用nosort關鍵字創建索引:
默認情況下,在表中創建索引的時候,會對表中的記錄進行排序,排序成功后再創建索引。但是當記錄比較多的是,這個排序作業會占用比較多的時間,這也就增加了索引建立的時間(排序作業是在索引創建作業中完成)。有時候,我們導入數據的時候,如采用insert into 語句插入數據過程中同時采用Order by子句對索引字段進行了排序。此時如果在索引創建過程中再進行排序的話,就有點脫褲子放屁,多此一舉了。為此在重新創建索引時,如果表中的數據已經排好序了(按索引字段排序),那么在創建索引時就不需要為此重新排序。此時在創建索引時,數據庫管理員就可以使用NOSORT可選項,告訴數據庫系統不需要對 表中當記錄進行重新排序了。
采用了這個選項之后,如果表中的記錄已經按順序排列,那么在重新創建索引的時候,就不會重新排序,可以提高索引創建的時間,節省內存中的排序緩存空 間。相反,如果表中的記錄是不按索引關鍵字排序的話,那么此時采用NOSORT關鍵字的話,系統就會提示錯誤信息,并拒絕創建索引。所以在使用 NOSORT可選項的時候,數據庫管理員盡管放心大膽的使用。因為其實在不能夠使用這個選項的時候,數據庫也會明確的告知。為此其副作用就比較少,數據庫管理員只需要把這個可選項去掉然后重新執行一次即可。不過這里需要注意的是,如果表中的記錄比較少的話,那么使用NOSORT選項的效果并不是很明顯。
* 使用UNION ALL代替UNION:因為UNION ALL不會消除重復的rows,所以也無需進行sort操作。
* 使用Nested loop join代替sort-merge join
* 在經常使用order by子句的列上創建索引。
* 使用analyze時,只統計所需字段的數據:
ANALYZE … FOR COLUMNS或ANALYZE … FOR ALL INDEXED COLUMNS
* 對于ANALYZE COMPUTE,其統計結果更精確,但是需要進行一定的sort,對此,可以使用ESTIMATE子句來替代大表或cluster中的ANALYZE。
4)診斷工具:
* 在視圖v$sysstat中顯示的信息中有:
sorts (memory):完全在內存中進行的排序的次數
sorts (disk):請求臨時segments的I/O進行sorts的次數
sorts (rows):當前已經進行過的sort的rows的數量
* 在statspack輸出的report中也存在上述信息,并計算了部分平均值
* 視圖v$sort_segment和v$sort_usage顯示了當前臨時segment中的使用情況,以及那些user占用了這些臨時segment。
@@ 在具體診斷時,可計算磁盤sort和memory sort的比率,它應該小于5%。否則,如果此比率顯示了較大的磁盤排序,則需要考慮是否可以增大SORT_AREA_SIZE的設置。
@@ 注意的是:如果增大了sort area,則每個需要sort的進程所占用的memory可能都會增加,在一定程度上影響了OS的memory分配及paging和swapping。所 以當增加了sort_area_size后,考慮是否可以適當減小SORT_RESERVED_AREA_SIZE的值,不過此值的減小,在一定程度上減 少了內存的使用,但也可能附加著造成了I/O的可能性。
6) 監控臨時表空間:主要是查看V$SORT_SEGMENT視圖:
select tablespace_name, current_users, total_extents, used_extents, extent_hits, max_used_blocks, max_sort_blocks from v$sort_segment;
具體字段的意義如下:
CURRENT_USERS:Number of active users
TOTAL_EXTENTS :Total number of extents
USED_EXTENTS :Extents currently allocated to sorts
EXTENT_HITS: Number of times an unused extent was found in the pool
MAX_USED_BLOCKS: Maximum number of used blocks
MAX_SORT_BLOCKS :Maximum number of blocks used by an individual sort
7)臨時表空間的設置:
默認臨時表空間的存儲參數對于sort segment都是適用的,只是它們有無限的extents。
設置臨時表空間的參數時,先要考慮sort_area_size的值。temporary tablespace的initial和next參數應該是sort_area_size的整數倍,并要考慮額外的segment header的空間。將PCTINCREASE設置為0 。
可以為users指定不同的temporary tablespace,并且可以將temp tablespace放在不同的磁盤上,對于查看使用情況,可以看v$sort_usage
select username, tablespace, contents, extents, blocks from v$sort_usage;
此外,還可查看V$TEMPFILE和DBA_TEMP_FILES可以獲得temporary tablespace的相關信息。
1、redo log buffer:
當時常遇到較大的事務時,增大log buffer可以減少不必要的log file I/O操作。commit操作將會flush log buffer,頻繁的commit可以考慮較小的buffer size。log_buffer最小為64K。
①對redo log buffer的診斷:
** 查看動態視圖:v$session_wait查看當前是否正有對log buffer的請求等待。
select sid, event, seconds_in_wait, state from v$session_wait where event = ‘log buffer space%’;
** 計算redo buffer allocation的重試的出現概率,此值應該盡量接近0,不應該大于1%,如果該值不斷增加,說明大量對redo log buffer的等待。
select name, value from v$sysstat where name = ‘redo buffer allocation retries’; –顯示了user 進程等待log buffer中的space所重試的次數。
select name, value from v$sysstat where name = ‘redo log space requests’;
引起等待的原因可能是由于log buffer過小,或是checkpoint,或是log switching所致。
對此,可以嘗試:增大log_buffer的值;或是改善checkpoint或歸檔進程。
** SECONDS_IN_WAIT值顯示的是除了由于log swith以外造成的log buffer等待的時間。它表明redo buffer被寫滿的速度要大于LGWR寫logfile的速度。也可能反映在redo logfile上的I/O存在沖突。
如果懷疑是LGWR的問題,可以繼續查看:
@@ 是否存在I/O沖突,是否redo log file存放在分開的快速存儲設備上。
@@ 查看日志切換的次數,考慮是否是切換太頻繁,是否需要增大log file 的size。
select event, total_waits, time_waited, average_wait from v$system_event where event like ‘log file switch completion%’;
@@ 如果DBWn在尚未完成checkpointing file時,LGWR在此需要相應的文件時,會引起LGWR的等待。對此可以從alert.log文件中查看到相關信息。查看當前是否有未完成的checkpoint事件:
select event, total_waits, time_waited, average_wait from v$system_event where event like ‘log file switch (check%’;
查看參數LOG_CHECKPOINT_INTERVAL和LOG_CHECKPOINT_TIMEOUT是否恰當;并查看redo log file的size和group數。
@@ 如果歸檔進程不能及時的將redo logfile,也可能會引起LGWR的寫入等待。
對此,先確認歸檔目錄沒有滿,適當增加redo log 的groups。下面的SQL顯示了由于歸檔問題引起的log file switch等待統計。
select event, total_waits, time_waited, average_wait from v$system_evnet where event like ‘log file switch (arch%’;
可以適當增大參數LOG_ARCHIVE_MAX_PROCESSES從而在大負荷量時增多歸檔進程。
@@ 如果將DB_BLOCK_CHECKSUM設置為true,會因此增加性能上的開支。
此外,盡可能減少redo的操作:
** 直接路徑的loading在非歸檔模式下,是不記錄redo log的
** 在歸檔模式下,直接路徑的loading可以使用nologging mode
** 直接insert也可使用nologging mode
** 部分sql可以使用nologging mode
但要明確,即使對table、index、tablespace使用nologging模式,但對于部分操作仍然會產生redo log。如create table … as select; create index … ; alter index … rebuild;
此外,nologging屬性對update, delete, 常規路徑的insert和各種DDL語句是不會起作用的。(這里貌似對insert添加hint也可以使其nologging)
2、監控Java池內存:select * from v$sgastat where pool = ‘java pool’;
1)用于限制Java session占用的內存的初始參數:
①JAVA_SOFT_SESSIONSPACE_LIMIT:當user session的java命令占用的內存超過該設置,將會發出warning,在跟蹤文件做一定的記錄,默認為1M。
②JAVA_MAX_SESSIONSPACE_SIZE:當user session的java命令占用內存超過該值,該session將被kill掉,默認為4G。
2)為Java Sizing SGA
①每裝載一個class,java引擎會使用8KB shared pool的內存,當裝載并處理大的jar files時,可占用50MBshared pool的內存。
②java pool是SGA中的一個組成部分,用于所有存在java code或是在EJE中存在數據的session中。instance startup時,會分配JAVA_POOL_SIZE指定大小的內存。一般會設置為50MB左右,默認是20MB。
3、multiple I/O slave:
4、multiple DBWR 進程
1) 多DBWn進程可以使用DB_WRITER_PROCESSES參數控制。它對于多cpu的SMP系統較有效。但是multiple DBWR與multiple I/O slave是不能同時使用的。
2)對其的調節:
select event, total_waits, time_waited from v$system_event where event=’free buffer waits’;
如果發現上述的SQL的total_waits是較大,可以考慮將增加DBWn進程的數量。
1、Shared Pool的組成
** library cache:存儲共享的SQL和PL/SQL代碼(解析和編譯后的SQL和pl/sql blocks——procedures,Functions,packages,triggers和匿名的pl/sql塊)使用最近最少使用算法管理 (LRU),避免語句的重復解析。
** data dictionary cache:保存字典對象的信息
** user global area(UGA):用于在沒有設置large pool時存放共享的server connection的信息。保存在Shared模式下session的信息。
當缺少data dictionary cache或library cache的代價比缺少database buffer cache的代價更高,所以對Shared pool的tuning有更高的優先權。在tuning Shared pool時主要關心library cache提高其hit ratio又更重要些。
當Shared pool過小,server為了管理有限的空間,需要消耗更多的cpu,從而引起爭用。
Shared pool從整體上可以通過參數shared_pool_size來調節。
2、library cache
在server查找是否有被緩沖的sql時,會先把statement轉換為ASCII文本,再進行hash函數的計算。
1)盡可能減少重復解析的次數:盡可能使code扁平化,使用bind variables;可以適當增大library cache的大小,從而減少由于cache不足造成的已經被解析的SQL被換出而引起重新解析的可能;如果在cache中保存的被解析的SQL相關聯的 schema object被修改,則該cache中的內容將不可用,所以要盡量避免這樣的事件發生。
2)避免library cache的碎片產生:為較大的內存需求保留一定的內存,主要通過shared_pool_reserved_size參數設置;將常用的較大的SQL和 PL/SQL對象pinning到內存中,避免其被換出;為Oracle Shared server設置large pool;盡量少使用較大的匿名blocks,用小的PL/SQL包的方法代替;在Oracle Shared Server中測量共享進程所用的session內存。
3)在v$librarycache中保存了每類數據保存在library cache中的統計信息。其中,三個字段較為重要:gets,顯示了相應item總的請求數量;pins,顯示了執行的次數;reloads顯示了被換出后重載的次數
4)調節library cache的診斷工具:
** v$sgastat
** v$librarycache
eg:sql> select namespace, gethitratio from v$librarycache; –獲得命中率,在OLTP中應該高于90%,如果沒有達到可以考慮以下方法:
a)提高應用程序代碼效率(通過綁定變量,避免SQL的硬解析)
b)增加共享池的大小(增加之前先通過v$sgastat查詢是free memory是否足夠大,有無增加共享池必要)
** v$sqltext:full SQL text
eg:sql> select sql_text, users_executing, executions, loads from v$sqlarea;
sql> select * from v$sqltext where sql_text like ’select %’;
** v$db_object_cache:緩沖的DB object,包括packages、tables或是SQL中參照的別名
** v$sqlarea:統計了所有的共享cursor和相應的sql的前1000個字符
** 如果重載的比率大于1%,需要考慮增大shared_pool_size。
sql> select sum(pins) “executions”, sum(reloads) “cache misses”, sum(reloads)/sum(pins) from v$librarycache;
在statspack report中,library cache activity (Instance state activity)的內容也顯示了此信息:parse count(total、hard、failure)
5)還需要明確的是多次的修改對象,也可能使library cache的內容被標記為invalid,從而造成reload-to-pins值增大。在v$librarycache中的invalidations 字段顯示了標記為invalid的次數。注意:analyze語句可用使標記為invalid。
sql>select namespace, pins, reloads, invalidations from v$librarycache;
可以查詢v$shared_pool_advice查看oracle建議使用共享內存,也可以通過oracle 的OEM查看共享內存圖。
6)與緩沖的執行計劃的相關的view:
** 動態性能視圖v$sql_plan可用于查看緩沖了的cursor的的執行計劃信息,它比plan_table表還多7個字段,兩者中的相同字段的值是一 致的。此外在v$sql視圖中添加了一個字段plan_hash_value,它為一個hash值,用于匹配執行計劃。與v$sqltext、 v$sql_plan、v$sqlarea中的hash_value字段對應。
7)測試applications:對應已經存在的application,先分配一個較大的shared_pool_size,開啟應用,計算當前使用的共享內存:
select sum(sharable_mem)
from v$db_object_cache
where type=’PACKAGE’ or type=’PACKAGE BODY’
type = ‘FUNCTION’ or type = ‘PROCEDURE’;
對于相關的SQL語句,需要通過v$SQLAREA查詢:
select sum(sharable_mem) from v$sqlarea where executions>5;
此外,也可以假設在每個user每打開一個cursor將增加250 bytes。這可以測試application在高峰期的shared pool的占用:
select sum(250* users_opening) from v$sqlarea;
在測試環境中,可以根據user的多少來估算打開的cursors數量。
select 250 * value bytest_per_user
from v$sesstat s, v$statname n
where s.statistic# = n.statistic# and n.name = ‘opened cursors current’ and s.sid=15;
這樣,在理想情況下,application中將占用的library cache大約是上述的總和加上少量的動態SQL。
8)large memory的存在必要性在于滿足較大的連續內存的需求,可以通過large_pool_size和 shared_pool_reservered_size來設置。一般會建議將其設置為shared_pool_size 的10%,如果設置為50%或以上,系統將報錯。
通過視圖v$shared_pool_reserved可以幫助tuning其大小。其中最好的目標是設置使request_misses(由于 large mem不足,通過LRU實現的flush)的長期統計結果接近0。還有一個procedure工具 dbms_shared_pool.aborted_request_threshold,用于限制shared pool在出現ORA-4031之前被flush
對于其調節:如果v$shared_pool_reserved中的request_misses值不為0并且不斷增加,需要考慮增加 shared_pool_reserved_size;如果request_misses為0,并且free_memory=>50%,考慮減少 shared_pool_reserved_size;v$shared_pool_reserved中的request_failures(顯示了沒有 memory用于滿足請求)>0并不斷增加,可以適當考慮減小shared_pool_reserved_size或增大 shared_pool_size。
9)將large object保存在內存中。
通過下面的語句可以查看在內存中已經cache了那些對象:
select * from v$db_object_cache
where sharable_mem > 10000 and (type=’PACKAGE’ or type = ‘PACKAGE BODY’ or
type = ‘FUNCTION’ or type = ‘PROCEDURE’) and kept = ‘NO’;
需要被pin入內存中的對象主要有:常用的較大的存儲對象,如standard、diutil包;編譯的常用的triggers;sequences。最 好在開機時就將其pin入內存中(我以為這里可以編寫適當的開機trigger)。這樣,既是使用命令alter system flush shared_pool時,也不會講這些object flush掉。
具體pin對象到內存的方法可以使用DBMS_SHARED_POOL.keep存儲過程。可以用unkeep方法解除其pin狀態。
10)對于匿名pl/sql塊:可以先在視圖v$sqlarea中找到相應的sql_text,并將其適當的改為packaged Functions來執行。
select sql_text from v$sqlarea where command_type = 47 and length(sql_text) > 500;
此外,可以適當的將這些匿名的PL/SQL blocks pin入內存,如下:
declare /* KEEP_ME */ x number;
begin x := 5;
end;
select address, hash_value from v$sqlarea where command_type = 47 and sql_text like ‘%KEEP_ME%’;
execute dbms_shared_pool.keep(‘address, hash_value’);
11)其他影響library pool的參數
** open_cursors:此參數定義了user進程可分配到的私有SQL area中可以引用的cursor的數量。這些私有SQL area將一直存在,直到cursor被關閉。所以應用中應該及時關閉不用的cursor。
** cursor_space_for_time:其為Boolean值,默認為false,如果設置為true,則共享 SQL areas中將不會把其標識為過期,直到其被關閉。不要將其設置為true,除非v$librarycache中的reload始終保持0時再考慮。當應 用中使用了form或大量的動態SQL,應設置為false。
** session_cached_cursors:此參數用于同一個user會經常解析同一個sql的情況。這會經常出現在form的應用中。當設置了該值,會將關閉的游標的解析仍然cache在內存中,用于后面的軟解析。
為了驗證設置是否恰當,可以查證v$sesstat中的”session cursor cache hits”和”parse count”的值,如果parses 結果的hits比較小,則考慮增加該值,但是,其增加的開支來自于memory。
3、data dictionary cache及其術語、tuning:
1)了解一些術語:
gets:對某object請求的總次數;
getmisses:顯示了data請求造成cache misses的次數
當instance被剛剛startup時,dictionary cache中是空的,所以任何sql都會引起getmisses的增加,但是隨著大量data被讀入cache,getmisses也會減少。最終,將達到一個穩定的平衡狀態。
對data dictionary的調節只能通過間接的調節shared_pool_size。
診斷data dictionary的工具有:
** 視圖v$rowcache:主要需要關注的字段是parameter、gets和getmisses
** 在statspack的report中,有相關的內容,其中每個數據字典項的misses的百分比大多數應該< 2%,整個Dictionary Cache應該< 15%。report中的cache usage是cache的實體被使用的次數。
sql>select 1-sum(getmisses)/sum(gets) "dta dic hitration" from v$rowcache;
pct SGA是用于data dictionary cache的SGA的比率。
查看getmisses比gets的總比率的方法:
select parameter, gets, getmisses from v$rowcache where parameter=’dc_objects’ or parameter=’dc_synonyms’;
應盡量將該比率降低到<15%的情況。否則,考慮增加shared_pool_size。
4、UGA和Oracle shared Server
在不同的Oracle Server模式下,UGA的位置也不同,具體如下圖:
如果使用的Oracle Shared Server模式,并且沒有設置large pool,則user的session data和cursor state將存儲在shared pool中,而非dedicated Server模式中的PGA中。sort area和private SQL area包含在session data中。在這種模式的Server中應增加shared_pool_size,PGA將變小。
相關的查詢:
select sum(value) || ‘ bytes’ “total session memory” from v$mystat, v$statname
where v$statname.name=’session uga memory’ and v$mystat.statistic#=v$statname.statistic#;
select sum(value) || ‘ bytes’ “total session memory” from v$sesstat, v$statname
where v$statname.name=’session uga memory’ and v$sesstat.statistic#=v$statname.statistic#;
select sum(value) || ‘ bytes’ “total session memory” from v$mystat, v$statname
where v$statname.name=’session uga memory max’ and v$mystat.statistic#=v$statname.statistic#;
5、Large Pool
它是在shared_pool_size之外被分配的,設置它的主要好處在于:
1.它可以用于給I/O服務器進程(dbwr_io_salves,操作系統不支持異步IO,用它來模擬異步)
2.backup、resort進程提供所需的較大的內存,
3.共享服務器的會話內存
4.并行查詢消息處理
從而降低shared pool產生碎片的可能及其帶來的開支。
它的大小由參數large_pool_size決定。
sql>show parameter large_pool_size
它的使用情況:
sql>select * from v$sgastat where pool='large pool'
1、overview
buffer cache中緩沖了數據文件中的data blocks,是SGA的一部分,可以被所有的進程共享。為了提高性能,Server 進程一次讀入多data blocks,DBWn一次寫入多個data blocks到data file。
相關的初始化參數有:
DB_CACHE_SIZE:指定默認的buffer pool的size,以bytes為單位。
DB_KEEP_CACHE_SIZE:以bytes為單位,指明keep buffer pool的大小。
DB_RECYCLE_CACHE_SIZE:以bytes為單位,指明recycle buffer pool的大小。
在Oracle8i中,有以下特點:
** buffer cache的大小事由DB_BLOCK_BUFFERS * DB_BLOCK_SIZE決定的;
** 在某個時間點,buffer cache中可能存在同一個data block的多個copies。只有一個是當前實際的block。但是Server為了時間讀一致性,結合使用rollback信息,滿足不同的查詢。
** buffer cache中的blocks通過兩個lists進行管理:①LRU list;②dirty list
** buffer cache中的blocks可能有三種狀態:①free buffers:其在disk和memory中是一致的,可以被重用;②dirty blocks:disk和memory中的數據不同,只有這些blocks被寫入disk,才可被重用;③pinned blocks:當前正在被訪問的blocks
2、buffer cache Sizing的參數(9i中)
** 支持多種大小的block,system的block大小仍用db_block_size設置(后面稱其為primary block size),但其他tablespace可以有自己不同的block size。
** 默認的與primary block size相關的buffer pool通過db_cache_size設置。DB_KEEP_CACHE_SIZE和DB_RECYCLE_CACHE_SIZE與DB_CACHE_SIZE是獨立的。
** 從9i開始對SGA的infrastructure修改變為動態的,可以不必shutdown在startup。
注:由于動態SGA的分配,也引入的新的分配單元granule。可以通過v$buffer_pool監控到buffer cache中granule的分配與回收
1)granule:在9i中,SGA組件分配回收的單位是granule。是一段連續的虛擬內存分配單位。其大小要依賴于對總SGA的估計:如果估計 SGA不足128MB,則設置為4MB,否則設置為16MB。當instance startup時,Server分配granule實體,組成SGA_MAX_SIZE的大小,并分配個SGA的不同組件。最小的SGA中要有3個 granules,分別擁有redo buffer、data buffer cache和shared pool。dba可以通過alter system動態的增加SGA的某個組件的memory大小,但是必須確保有足夠的free granules方可成功;memory granules不會被自動釋放從而滿足其他組件memory增加的需求,可以減小某些組件的memory granules,但是縮減granules必須確保是未使用的,方可成功。在動態添加組件memory時,必須注意:新的cache sizes必須是granule size的整數倍;總的SGA size不可超過MAX_SGA_SIZE;DB_CACHE_SIZE不能設置為0(注意這是9i中,而我現在安裝的是11g,情況有所不同啊)
2)動態buffer cache的advisory parameter:通過設置db_cache_advice參數為on,可以提供buffer cache size的合并和預測統計數據,從而輔助DBA調節buffer cache。db_cache_advice的可以設置為:off關閉advisory,并收回相應的memory;ready,關閉advisory, 但保留其memory;on,打開advisory,從而引起一定的cpu和memory開銷。為了避免從off過渡到on時引起的ORA-4031 err,需要現將其設置為ready。
3)buffer cache advisory收集的數據信息主要可以通過v$db_cache_advice視圖顯示
select size_for_estimate, buffers_for_estimate, estd_physical_read_factor,estd_physical_reads
from v$db_cache_advice where name=’DEFAULT’
and block_size = (select value from v$parameter where name = ‘db_block_size’)
and advice_status = ‘ON’;
4)管理database buffer cache
①服務器進程和database buffer cache:當server需要申請一個block時,需要一些步驟:
i)server通過hash函數檢查被請求的block是否已經在buffer cache中了。如果被找到了,則將其從LRU list中移動到尾部。這將是邏輯讀。如果沒被找到,server 進程需要將block從data file中讀入。
ii)在從data file中讀入時,server 進程將先查找LRU list,找到一個free block。
iii)當查找LRU list時,server 進程同時會將相應的dirty block移動到dirty list中。
iv)如果dirty list超過了其threshold size,server將給DBWn發信號,讓其flush在dirty list中的 dirty blocks到data file中。如果server在查找的threshold范圍內找不到空閑的block時,DBWn也會受到類似信號,直接將LRU list中的block寫入data file。
v)當空閑塊被找到之后,server將相應的block讀入空閑塊。并將其放入LRU list的尾部。
vi)如果block不一致,server將通過當前block和rollback segments重建一個早期版本。
vii)此外,對于DWRn進程,每過3秒,會先將LRU list中的dirty blocks移動到dirty list中,隨后將dirty list中的blocks寫入data file。
viii)當LGWR進程發起checkpoint signals時,DWRn也會先將LRU list中的dirty blocks移動到dirty list中,隨后將dirty list中的blocks寫入data file。
ix)當發出命令alter tablespace offline或是進行在線備份時,DBWn也會先將LRU list中的dirty blocks移動到dirty list中,隨后將dirty list中的blocks寫入data file。
x)在刪除object時,DBWn會先將與該object有關的dirty blocks寫入磁盤。
xi)在正常的normal、immediate、transactional shutdown時,也會flush data buffer。
2、data buffer size的調節
1)調節的目標是提高data cache中的命中率,從而減少實際的物理I/O。
2)診斷的工具主要是觀察cache的命中率(使用v$sysstat和utlbstat.sql與utlestat.sql等)和v$db_cache_advice
select name,value from v$sysstat
where name in (’session logical reads’, ‘physical reads’,
‘physical reads direct’,'physical reads direct (lob)’);
• physical reads: Number of blocks read from disk
• physical reads direct: Number of direct reads, does not require the cache
• physical reads direct (lob): Number of direct reads of large binary objects
• session logical reads: Number of logical read requests
命中率 = 1- (physical reads – physical reads direct – physical reads direct (lob)) / session logical reads
由于v$sysstat中的數據是自instance startup后的累計數據,所以在startup不久就進行此查詢獲得的結果是沒有太大意義的。
v$buffer_pool描述了multiple buffer pools的情況,v$buffer_pool_statistics顯示了各個pool的統計情況
select name, physical_reads, db_block_gets,consistent_gets from v$buffer_pool_statistics;
v$bh:描述了保存在cache中的數據blocks
3)tuning:
改變cache的命中率,DBA可以:
①當出現下面的情況時,可以考慮增加buffer cache size:
* cache的命中率不足90%
* 有足夠的memory,不會引起額外的缺頁現象
* 之前對cache的增加有較好的收效
②如果是由于data的訪問特點造成了較低的命中率,可以考慮為不同的blocks使用多buffer pools,并適當的將table配置緩沖到cache中
③此外,對于sorting和parallel reads,如果可以的話,避免其讀入cache。
需要注意的是:還需考慮OS的caching的影響。
4)對于命中率主要受到數據訪問方式的影響
* 全表掃描
* data和application的設計
* large table的隨機訪問
* cache的不均勻分布
5)對于cache命中率的評估:
* 如果上一次對data buffer cache的增加沒有活動較好的收效,就不要繼續對其增加。
* 當查看命中率時,要明確:在全表掃描時遇到的blocks并沒有放入到LRU的head部分,所以重復掃描不會造成blocks的緩沖
* 由于設計和應用層造成的重復掃描某個大表時,將會造成性能問題。所以建議盡量在一次讀取數據,并適當建立索引。
6)使用multiple buffer pools:當使用multiple buffer pools方法時,objects被分配到那個pool要依靠其訪問的方式。有三類buffer pools(我記得在11g中更靈活,不止三類了):
* keep:此類pool用于存放可能被reused的對象。
* recycle:該pool被用于存放reused可能性較小的blocks。
* default:同single buffer cache中的cache是一致的。
主要是通過DB_CACHE_SIZE, DB_KEEP_CACHE_SIZE和DB_RECYCLE_CACHE_SIZE參數設置的。它們都是動態的。在9i中其latches是自動分配 的。在8i中需要用db_block_lru_latches分配,一般是至少每50個blocks分配一個latch。
在使用multiple buffer pools時,可以使用如下sql語句:
CREATE INDEX cust_idx .. STORAGE (BUFFER_POOL KEEP);
ALTER TABLE customer STORAGE (BUFFER_POOL RECYCLE);
ALTER INDEX cust_name_idx STORAGE (BUFFER_POOL KEEP);
當發出alter命令來修改buffer pool時,之前的blocks仍保存在原有的buffer中,新load的才會被cache到新buffer pool中。
因為buffer pool是以segment為單位分配的,有多個segments組成對象就可能被緩沖到不同的buffer pools中。
7)keep buffer pool的使用:在確定keep pool大小時,可以在設計時考慮要把那些object放入該buffer,然后求和即可。具體可以如下:
analyze table hr.countries estimate statistics;
select table_name, blocks from dba_table where owner = ‘HR’ and table_name = ‘COUNTRIES’;
具體可以編寫腳本先后對DBA_TABLES, DBA_TAB_PARTITIONS, DBA_INDEXES和DBA_CLUSTERS進行analyze。并根據訪問的特性,將部分對象分對象所需要的blocks加總計算。
8)對recycle pool的設置,不要設置過小,以免在事務或SQL還沒有被執行完,就已經被換出了。
對其進行監控、并確定其size的工具可以使用v$sysstat中的物理讀(physical reads)的統計信息,此外可以使用v$cache視圖,它需要在sys下運行catparr.sql腳本進行創建。
v$cache視圖從object的角度對buffer pool的blocks的占用進行了統計。其實v$cache是為了Oracle parallel server(OPS)而發布的,在執行catparr.sql時,還創建了其他只在OPS中才有用的視圖。它還映射了DB object在datafile中的 extents。當創建了新的object后,需要重新運行該腳本。
在決定recycle pool大小時,可先令recycle pool disable;運行catparr.sql;在DB使用高峰期,運行下述語句計算每個object占用了多少blocks:
select owner#, name, count(*) blocks from v$cache group by owner#, name;
根據不同對象的訪問特點,確定哪些應該被放入recycle pool并加總這些對象所占用的blocks,這里我用rcb來表示這個數。分配rcb/4大小的recycle pool。
9)跟蹤物理讀的方法有很多:用調節工具如Oracle trace manager、sqlplus autotrace或是tkprof運行sql都可以跟蹤其執行時的物理讀。此外可以查看視圖v$sess_io。例如:
select s.username, io.block_gets, io.consistent_gets, io.physical_reads
from v$sess_io io, v$session s where io.sid = s.sid;
10)計算multiple pools下的命中率,可以使用視圖v$buffer_pool_statistics
select name, 1-(physical_reads/(db_block_gets+consistent_gets)) “hit_ratio”
from v$buffer_pool_statistics where db_block_gets + consistent_gets > 0;
11)在考慮不同的object使用何種pool時,可從下面的觀點出發:
** 對于keep pool:blocks將被頻繁使用;segments的大小應該小于default buffer pool大小的10%
** recycle pool:在所屬的transaction之外將很少被reused;segment的大小是default buffer pool兩倍之多
12)將table caching:如果server通過全表掃描獲得數據,blocks將被放到LRUlist的尾部,并可能會很快因缺少free blocks被換出。對此可以選擇將整個表cache到list的最近經常使用的部分。具體可以在create table時使用cache關鍵字,或alter table使用cache,或使用cache的暗示。但是如果將太多的table放入LRU list的most recently used端,可能會使buffer cache非常擁擠。
13)其他cache performance indicators
①select name, value from v$sysstat where name = ‘free buffer inspected’;
如果此獲得的等待統計很大,并不斷增加需要考慮增加buffer pool。其表示了在查找free buffer是skipped的buffer。之所以skipped,是由于dirty或pinned。
②select event, total_waits from v$system_event where event in (‘free buffer waits’, ‘buffer busy waits’);
除了v$system_event,也可從v$session_wait視圖。buffer busy wait表示有多個進程嘗試同時訪問buffer cache中的部分buffers。通過v$waitstat視圖可以查看所有不同buffer被等待統計數據。buffer busy wait中包含的類型有data block、segment header、undo header和undo block。如果在v$waitstat視圖中:
* data block(tables或indexes的contention)較大:查看sql是否正確使用了索引;查看是否存在right-hand- indexes的情況(例如索引上的數據是由sequence產生);考慮是否使用segment-space管理或是增加free lists避免多個進程同時向一個block中insert。
* undo header:顯示了在回滾段header上沖突:對此如果不使用自動的undo管理,則嘗試增加更多的rollback segments。
* undo block:顯示了在rollback segment block的沖突:如果不使用自動undo的管理,考慮增大rollback segment的sizes。
* free buffer waits:表示server進程不能找到free buffer了,signal DWRn寫入dirty blocks,這個過程引起的等待。對此,可以嘗試提升DBWR的效率,另一方面可以考慮是不是buffer cache設置過小了。
引起DBWR高效工作的原因可能是:i/o系統慢;i/o可能在等待某些資源,如latches;buffer cache太小了,造成DBWR需要不斷寫入臟數據;buffer cache太大了,一個DBWR進程迅速的無法釋放足夠的buffer。對此,可以進一步查看等待DBWR的session,獲知具體的問題。
14)free list:它為每個對象維護一個blocks list用于數據的insert,free lists的數量是可以動態設置的。但是對于單核cpu的系統,使用多free lists的好處不大。調節free list的目的是可以減少insert時對free lists的爭用沖突。當使用automatic free space management時,Oracle使用bitmap存儲free-list的信息,在數據庫上降低了沖突,free lists就可以不用使用了。
** 診斷free list的沖突的存在:
如上,通過v$session_wait獲得等待時間具體在等待哪一個block,通過v$waitstat中class為segment header顯示了等待freelist的數據,v$system_event視圖中event字段為’buffer busy waits’的記錄顯示freelist的等待的整體信息。我們可以通過dba_segments表查看是那些segments需要增加 freelist。具體的查詢語句如下:
select s.segment_name, s.segment_type, s.freelists,
w.wait_time, w.seconds_in_wait, w.state
from dba_segments s, v$session_wait w
where w.event=’buffer busy waits’
and w.p1 = s.header_files and w.p2 = s.header_block;
對freel ist的修改可以使用alter table語句進行動態修改,但是對于自動segment空間管理的模式下是不能對freelist的數量進行修改的。
對于降低buffer busy waits可采取的措施有:
** 對于data blocks:適當改變pctfree或pctused;查看是否有right-hand index;增大initrans的值,降低每個block中存放的記錄的數量。
** 對于segment header:使用free lists或增加free lists的數量,使用free list groups。
** 對free list blocks:增加更多的free lists。(在Oracle Parallel Server中,應該確保每個instance有自己的free list group)
15)自動管理空閑空間。從9i開始,可以使用位圖對空閑和使用的blocks使用自動空間管理,與free list相比,性能更好。它只能在創建tablespace時指明,此后,建立在該表空間上的所有segment都將以自動空間管理方式管理。
create tablespace tsp datafile ‘/path/datafile.dbf’ size nM
extent management local segment space management auto;