幾個簡單的步驟大幅提升Oracle性能--我優化數據庫的三板斧。 sql
數據庫優化的討論能夠說是一個永恆的主題。資深的Oracle優化人員一般會要求提出性能問題的人對數據庫作一個statspack,貼出數據庫配置等等。還有的人認爲要抓出執行最慢的語句來進行優化。但實際狀況是,提出疑問的人極可能根本不懂執行計劃,更不要說statspack了。而我認爲,數據庫優化,應該首先從大的方面考慮:網絡、服務器硬件配置、操做系統配置、Oracle服務器配置、數據結構組織、而後纔是具體的調整。實際上網絡、硬件等每每沒法決定更換,應用程序通常也沒法修改,所以應該着重從數據庫配置、數據結構上來下手,首先讓數據庫有一個良好的配置,而後再考慮具體優化某些過慢的語句。我在給個人用戶系統進行優化的過程當中,總結了一些基本的,簡單易行的辦法來優化數據庫,算是個人三板斧,呵呵。不過請注意,這些不必定廣泛使用,甚至有的會有反作用,可是對OLTP系統、基於成本的數據庫每每行之有效,不妨試試。(注:附件是Burleson寫的用來報告數據庫性能等信息的腳本,本文用到) 數據庫
一.設置合適的SGA 緩存
經常有人抱怨服務器硬件很好,可是Oracle就是很慢。極可能是內存分配不合理形成的。 服務器
(1)假設內存有512M,這一般是小型應用。建議Oracle的SGA大約240M,其中:共享池(SHARED_POOL_SIZE)能夠設置60M到80M,根據實際的用戶數、查詢等來定。數據塊緩衝區能夠大體分配120M-150M,8i下須要設置DB_BLOCK_BUFFERS,DB_BLOCK_BUFFER*DB_BLOCK_SIZE等於數據塊緩衝區大小。9i 下的數據緩衝區能夠用db_cache_size來直接分配。 網絡
(2)假設內存有1G,Oracle 的SGA能夠考慮分配500M:共享池分配100M到150M,數據緩衝區分配300M到400M。 數據結構
(3)內存2G,SGA能夠考慮分配1.2G,共享池300M到500M,剩下的給數據塊緩衝區。 oracle
(4)內存2G以上:共享池300M到500M就足夠啦,再多也沒有太大幫助;(Biti_rainy有專述)數據緩衝區是儘量的大,可是必定要注意兩個問題:一是要給操做系統和其餘應用留夠內存,二是對於32位的操做系統,Oracle的SGA有1.75G的限制。有的32位操做系統上能夠突破這個限制,方法還請看Biti的大做吧。 性能
二.分析表和索引,更改優化模式 測試
Oracle默認優化模式是CHOOSE,在這種狀況下,若是表沒有通過分析,常常致使查詢使用全表掃描,而不使用索引。這一般致使磁盤I/O太多,而致使查詢很慢。若是沒有使用執行計劃穩定性,則應該把表和索引都分析一下,這樣可能直接會使查詢速度大幅提高。分析表命令能夠用ANALYZE TABLE 分析索引能夠用ANALYZE INDEX命令。對於少於100萬的表,能夠考慮分析整個表,對於很大的表,能夠按百分比來分析,可是百分比不能太低,不然生成的統計信息可能不許確。能夠經過DBA_TABLES的LAST_ANALYZED列來查看錶是否通過分析或分析時間,索引能夠經過DBA_INDEXES的LAST_ANALYZED列。 優化
下面經過例子來講明分析先後的速度對比。(表CASE_GA_AJZLZ大約有35萬數據,有主鍵)首先在SQLPLUS中打開自動查詢執行計劃功能。(第一次要執行\RDBMS\ADMIN\utlxplan.sql來建立PLAN_TABLE這個表)
SQL> SET AUTOTRACE ON
SQL>SET TIMING ON
經過SET AUTOTRACE ON 來查看語句的執行計劃,經過SET TIMING ON 來查看語句運行時間。
SQL> select count(*) from CASE_GA_AJZLZ;
COUNT(*)
----------
346639
已用時間: 00: 00: 21.38
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'CASE_GA_AJZLZ'
……………………
請注意上面分析中的TABLE ACCESS(FULL),這說明該語句執行了全表掃描。並且查詢使用了21.38秒。這時表尚未通過分析。下面咱們來對該表進行分析:
SQL> analyze table CASE_GA_AJZLZ compute statistics;
表已分析。已用時間: 00: 05: 357.63。而後再來查詢:
SQL> select count(*) from CASE_GA_AJZLZ;
COUNT(*)
----------
34663
已用時間: 00: 00: 00.71
Execution Plan
0 SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=351 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FAST FULL SCAN) OF 'PK_AJZLZ' (UNIQUE) (Cost=351
Card=346351)
…………………………
請注意,此次時間僅僅用了0.71秒!這要歸功於INDEX(FAST FULL SCAN)。經過分析表,查詢使用了PK_AJZLZ索引,磁盤I/O大幅減小,速度也大幅提高!下面的實用語句能夠。用來生成分析某個用戶的全部表和索引,假設用戶是GAXZUSR:
SQL> set pagesize 0
SQL> spool d:\analyze_tables.sql;
SQL> select 'analyze table '||owner||'.'||table_name||'
compute statistics;' from dba_tables where owner='GAXZUSR';
SQL> spool off
SQL> spool spool d:\analyze_indexes.sql;
SQL> select 'analyze index '||owner||'.'||index_name||'
compute statistics;' from dba_indexes where owner='GAXZUSR';
SQL> spool off
SQL> @d:\analyze_tables.sql
SQL> @d:\analyze_indexes.sql
解釋:上面的語句生成了兩個sql文件,分別分析所有的GAXZUSR的表和索引。若是須要按照百分比來分析表,能夠修改一下腳本。經過上面的步驟,咱們就完成了對錶和索引的分析,能夠測試一下速度的改進啦。建議按期運行上面的語句,尤爲是數據通過大量更新。固然,也能夠經過dbms_stats來分析表和索引,更方便一些。可是我仍然習慣上面的方法,由於成功與否會直接提示出來。另外,咱們能夠將優化模式進行修改。optimizer_mode值能夠是RULE、CHOOSE、FIRST_ROWS和ALL_ROWS。對於OLTP系統,能夠改爲FIRST_ROWS,來要求查詢儘快返回結果。這樣即便不用分析,在通常狀況下也能夠提升查詢性能。可是表和索引通過分析後有助於找到最合適的執行計劃。
三.設置cursor_sharing=FORCE 或SIMILAR 這種方法是8i纔開始有的,oracle805不支持。經過設置該參數,能夠強制共享只有文字不一樣的語句解釋計劃。例以下面兩條語句能夠共享:
SQL> SELECT * FROM MYTABLE WHERE NAME='tom'
SQL> SELECT * FROM MYTABLE WHERE NAME='turner'
這個方法能夠大幅下降緩衝區利用率低的問題,避免語句從新解釋。經過這個功能,能夠很大程度上解決硬解析帶來的性能降低的問題。我的感受可根據系統的實際狀況,決定是否將該參數改爲FORCE。該參數默認是exact。不過必定要注意,修改以前,必須先給ORACLE打補丁,不然改以後oracle會佔用100%的CPU,沒法使用。對於ORACLE9i,能夠設置成SIMILAR,這個設置綜合了FORCE和EXACT的優勢。不過請慎用這個功能,這個參數也可能帶來很大的負面影響!
四.將經常使用的小表、索引釘在數據緩存KEEP池中內存上數據讀取速度遠遠比硬盤中讀取要快,據稱,內存中數據讀的速度是硬盤的14000倍!若是資源比較豐富,把經常使用的小的、並且常常進行全表掃描的表給釘內存中,固然是在好不過了。能夠簡單的經過ALTER TABLE tablename CACHE來實現,在ORACLE8i以後可使用ALTER TABLE table STORAGE(BUFFER_POOL KEEP)。通常來講,能夠考慮把200數據塊以內的表放在keep池中,固然要根據內存大小等因素來定。關於如何查出那些表或索引符合條件,可使用本文提供的access.sql和access_report.sql。這兩個腳本是著名的Oracle專家 Burleson寫的,你也能夠在讀懂了狀況下根據實際狀況調整一下腳本。對於索引,能夠經過ALTER INDEX indexname STORAGE(BUFFER_POOL KEEP)來釘在KEEP池中。將表定在KEEP池中須要作一些準備工做。對於ORACLE9i 須要設置DB_KEEP_CACHE_SIZE,對於8i,須要設置buffer_pool_keep。在8i中,還要修改db_block_lru_latches,該參數默認是1,沒法使用buffer_pool_keep。該參數應該比2*3*CPU數量少,可是要大於1,才能設置DB_KEEP_CACHE_BUFFER。buffer_pool_keep從db_block_buffers中分配,所以也要小於db_block_buffers。設置好這些參數後,就能夠把經常使用對象永久釘在內存裏。
五.設置optimizer_max_permutations
對於多表鏈接查詢,若是採用基於成本優化(CBO),ORACLE會計算出不少種運行方案,從中選擇出最優方案。這個參數就是設置oracle究竟從多少種方案來選擇最優。若是設置太大,那麼計算最優方案過程也是時間比較長的。Oracle805和8i默認是80000,8建議改爲2000。對於9i,已經默認是2000了。
六.調整排序參數
(1) SORT_AREA_SIZE:默認的用來排序的SORT_AREA_SIZE大小是32K,一般顯得有點小,通常能夠考慮設置成1M(1048576)。這個參數不能設置過大,由於每一個鏈接都要分配一樣的排序內存。
(2) SORT_MULTIBLOCK_READ_COUNT:增大這個參數能夠提升臨時表空間排序性能,該參數默認是2,能夠改爲32來對比一下排序查詢時間變化。注意,這個參數的最大值與平臺有關係。