gdufo

           

          Sizing the Buffer Cache

           

          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;

          posted on 2010-01-12 12:27 gdufo 閱讀(708) 評論(0)  編輯  收藏 所屬分類: Database (oracle, sqlser,MYSQL)

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          收藏夾

          Hibernate

          友情鏈接

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 织金县| 嘉兴市| 万盛区| 左权县| 施秉县| 潼南县| 南乐县| 游戏| 同江市| 郁南县| 元阳县| 佛坪县| 蒲城县| 库尔勒市| 肇州县| 闵行区| 读书| 外汇| 昆明市| 资兴市| 文成县| 和平区| 施秉县| 锡林浩特市| 门源| 浪卡子县| 平度市| 嘉定区| 山阳县| 霍州市| 内乡县| 日土县| 蓝山县| 安塞县| 微博| 桦甸市| 扬州市| 建阳市| 会昌县| 襄城县| 沙坪坝区|