Buffer cache 的調整與優化(二)

beatony發表於2011-07-29
Buffer cache 的調整與優化(二)
分類: Oracle 效能優化 144人閱讀 評論(0) 收藏 舉報

--********************************

-- Buffer cache 的調整與優化()

--********************************

   

    Buffer cache 實際上細分為多個不同的Buffer cache,如keep poolrecycle pooldefault pool,下面描述不同buffer cache的使用。

    有關Buffer cache 的總體描述,請參考:Buffer cache 的調整與優化(一)

   

一、不同buffer pool的應用

        一個buffer pool即對應於一個oracle 資料塊,三種不同的pool實際上是針對在data buffer cache中塊的訪問的程度不同在通常的

    慣例下采取的方法。即對最熱塊,次熱快,以及冷塊存放到不同的buffer pool中。實際上這幾個不同的buffer pool除了分配的大小不同

    之外,所採用的演算法都是LRU演算法,因此對塊的快取以及淘汰(aged out)演算法實質一樣。

        任意一個不同的buffer pool都將根據訪問方式的不同而只快取讀取到的資料塊,即如果是全表掃描,則快取所有塊,如果是索引快速

    掃描,則快取索引的所有葉節點塊。   

       

        keep buffer cache            --對應keep pool

        recycle buffer cache         --對應recycle pool

        nk buffer caches             --對應db_nk_cache_size

        default buffer cache         --對應dafault pool

       

        keep pool

            對於經常訪問的小表將其常駐記憶體,即放置到keep pool。其作用是保證這部分經常訪問的資料能夠常駐記憶體而不被替換出記憶體,

        從而提高訪問這些資料的速度。這個池最好能夠保持99%的命中率,也就是說要保證這個池的大小能夠快取放於這個池的大部分物件。

       

        recycle pool

            對於不經常訪問的大segment,就可以考慮將其放置到recycle pool,以儘快將其淘汰出去。

           

        dafault pool

            普通物件的緩衝池,那些沒有在keep pool也沒有在recycle pool的物件將緩衝到這裡。

       

        nk buffer caches

            主要適用於不同平臺傳輸表空間,或根據業務需要來使用非標準表空間之外的表空間。

           

        如磁碟上資料檔案的最小I/O單元叫block一樣,buffer cache的最小單元(或者說結構)叫buffer

        每個bufferx$bh中每條記錄存在一一對應關係。

       

        注意:

            default buffer cache  = db_cache_size - db_keep_cache_size - db_recycle_cache_size - db_nk_cache_size

   

            sys@ORCL> select * from v$version where rownum < 2;

 

            BANNER

            ----------------------------------------------------------------

            Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

 

            sys@ORCL> select name,bytes/1024/1024 from v$sgainfo where name='Buffer Cache Size';

 

            NAME                      BYTES/1024/1024

            ------------------------- ---------------

            Buffer Cache Size                     192

                       

            sys@ORCL> select name,current_size,buffers,block_size  FROM v$buffer_pool;

 

            NAME            CURRENT_SIZE    BUFFERS BLOCK_SIZE

            --------------- ------------ ---------- ----------

            DEFAULT                  192      23952       8192

 

            sys@ORCL> alter system set db_recycle_cache_size=16m;

 

            sys@ORCL> alter system set db_keep_cache_size=16m;

 

            sys@ORCL> select name,current_size,buffers,block_size  FROM v$buffer_pool;

 

            NAME            CURRENT_SIZE    BUFFERS BLOCK_SIZE

            --------------- ------------ ---------- ----------

            KEEP                      16       1996       8192

            RECYCLE                   16       1996       8192

            DEFAULT                  160      19960       8192

 

            sys@ORCL> alter system set db_16k_cache_size=4m;

 

            sys@ORCL> select name,current_size,buffers,block_size  FROM v$buffer_pool;

 

            NAME            CURRENT_SIZE    BUFFERS BLOCK_SIZE

            --------------- ------------ ---------- ----------

            KEEP                      16       1996       8192

            RECYCLE                   16       1996       8192

            DEFAULT                  160      19960       8192

            DEFAULT                    4        252      16384

       

            從上面的設定可以看出,任意一個buffer pool大小的調整,不影響整個buffer_pool的大小。即任意buffer pool的增加,將使得

        default buffer pool的減小,反之,任意buffer pool尺寸的減少,default buffer pool的尺寸將會增加。

            其次,任意buffer pool的增加應考慮到Oracle 以及OS是否有足夠的記憶體來進行分配。如果是使用了ASMM管理,則應考慮整個

        sga_target < sga_max_size

           

二、大表段、大索引段隨機訪問的問題

    當使用LRU演算法時,對於大表段,索引段的隨機訪問,容易導致其他的並非最頻繁訪問的熱點塊從cache中被aged out.此外,這些隨機訪問

    的資料塊並不屬於熱塊,也很容易隨時被替換,通過下面的三種方法來避免該情況的產生:

        1.如果受影響的物件是索引,則判斷是否是精確的索引選擇,如果不是,則調整SQL語句。

        2.如果SQL語句已優化,則可以將被訪問的大段存放到recycle cache中。

        3.可以將一些小的熱點塊移入到keep buffer poolkeep buffer pool能夠最小化cache的丟失。

 

三、多個buffer pool的設定

 

        db_cache_size

        db_keep_cache_size

        db_recycle_cache_size

        db_nk_cache_size

       

    以上的引數為動態引數,使用下面的方式來調整,可以基於記憶體調整,也可以將引數更改到spfile

        alter system set db_keep_cache_size=nm scope = both | memory | spfile;

        alter system set db_16k_cache_size=nm;

        alter system set db_recycle_cache_size=nm;

    閂由Oracle RDBMS來自動分配

 

    進行了上述設定之後,可以基於這些不同的緩衝池來建立物件

        create index idx_obj

        storage(buffer_pool keep);

 

        alter table tb_obj

        storage(buffer_pool recycle);

 

        alter index idx_obj

        storage(buffer_pool keep);

       

    注:

        四個池除了使用不同的名稱且產生不同的作用之外,其內部演算法實質是一樣的,都是採用LRU演算法。

       

        一個segment只能放入到一個buffer pool.如果一個表或索引物件擁有多個segment,則不同的segment可以存放到不同的buffer pool.

        如何決定什麼樣的segment存放到何種buffer cache則根據業務需求來定。

        如果沒有指定buffer_pool短語,則表示該物件進入default型別的buffer cache

       

四、keep buffer pool的使用與優化

    將常用的小表物件常駐記憶體

        一般情況是物件的大小應當為少於default buffer pool 大小的10%

        根據下面的方法計算物件所佔用塊的總數,且該塊的總數大小應當小於於keep buffer pool的大小。

        計算所有將要放入到keep buffer cache物件的總塊數得到一個近似值,然後將稍微大於該近似值的尺寸指定給keep buffer pool

        可以通過查詢DBA_TABLES.BLOCKS DBA_TABLES.EMPTY_BLOCKS 獲得塊的資訊或者通過V$BH檢視segment所佔用的buffer

        對於放入keep buffer pool中的表資料,如果物件塊多於buffer pool數量,則以buffer pool數量為準進行快取,冷塊將被新塊置換。

 

        注:如果位於keep buffer pool中的物件尺寸增大,將不會被填充到keep buffer pool

            其次,如果有多個物件快取到keep buffer pool,而keep buffer pool不足以快取這些物件,按LRU演算法,先前位於keep buffer

                pool 的物件一樣會被aged out

                   

        首先使用包收集物件資訊

            sys@ORCL> exec dbms_stats.gather_table_stats('SCOTT','BIG_KEEP');

            sys@ORCL> select table_name,blocks,empty_blocks                        

              2  from dba_tables where owner='SCOTT' and table_name='BIG_KEEP';

 

            TABLE_NAME                    BLOCKS EMPTY_BLOCKS

            ------------------------- ---------- ------------

            BIG_KEEP                         180            0

       

        設定keep buffer pool的大小

            alter system set db_keep_cache_size=16m scope = both ;  --注意,該引數值的大小應根據實際情況設定

       

        將物件放置的keep buffer pool

            alter table big_keep

            storage(buffer_pool keep);

   

五、recycle buffer pool的使用與優化

    一旦事務被提交則這些塊將從recycle buffer pool中被清除

    物件的大小應當為多於default buffer pool 大小的兩倍

    recycle buffer pool需要具有一個事務所需要的全部塊

   

    下面將big_temp 置入到recycle buffer pool

        sys@ORCL> exec dbms_stats.gather_table_stats('SCOTT','BIG_RECYCLE');

   

        scott@ORCL> select blocks,empty_blocks from dba_tables            

          2  where table_name='BIG_RECYCLE' and owner='SCOTT';         

 

            BLOCKS EMPTY_BLOCKS

        ---------- ------------

              1062            0

       

        alter system set db_recycle_cache_size=16m scope = both ;  --注意,該引數值的大小應根據實際情況設定

       

        scott@ORCL> alter table big_recycle

          2  storage(buffer_pool recycle);

   

    使用檢視v$cache

        SELECT owner#

               ,NAME

               ,COUNT(*) blocks

        FROM v$cache

        GROUP BY owner#,NAME;

 

        SELECT s.username     --跟蹤recycle buffer poolI/O情況

               ,io.block_gets

               ,io.consistent_gets

               ,io.physical_reads

        FROM v$sess_io io,v$session s

        WHERE io.sid=s.sid;          

 

六、獲得buffer pool中的相關資訊

        檢視v$bh(基於檢視x$bh)顯示當前位於SGA中所有塊的詳細資訊。決定哪個段位於哪個緩衝區,所佔住的塊的個數等

       

    1.查詢buffer cache中不同物件佔住塊的個數(可以根據查詢將不經常訪問的大物件置於到recycle pool)

 

        SELECT o.owner, object_name, object_type, COUNT(1) buffers  --這個查詢獲得到經常訪問的物件,可以將其放到recycle pool

        FROM   SYS.x$bh, dba_objects o

        WHERE  (tch = 1 OR (tch = 0 AND lru_flag < 8))

               AND obj = o. object_id

               AND o.owner NOT IN ('SYSTEM', 'SYS')

        GROUP  BY o.owner, object_name, object_type

        ORDER  BY buffers;

       

        SELECT o.owner, object_name, object_type, COUNT(1) buffers   --這個查詢獲得到經常訪問的物件,可以將其放到keep pool

        FROM   SYS.x$bh, dba_objects o

        WHERE  tch > 10

               AND lru_flag = 8

               AND obj = o.object_id

               AND o.owner NOT IN ('SYSTEM', 'SYS')

        GROUP  BY o.owner, object_name, object_type

        ORDER  BY buffers;     

       

    2.查詢單個物件佔住buffer cache中塊的總個數 

        SELECT COUNT(*)

        FROM v$bh

        WHERE objd=(

        SELECT data_object_id 

          FROM Dba_Objects

        WHERE object_name=UPPER('big_table')

              AND owner='SCOTT'

              AND  status != 'free');

       

        COUNT(*)

        ----------

              4235             

             

    3.獲得所有不同的buffer pool 當前分配塊的總個數

        SELECT NAME

               ,block_size

               ,SUM(buffers)

        FROM v$buffer_pool

        GROUP BY NAME,block_size

        HAVING SUM(buffers)>0;     

 

        NAME       BLOCK_SIZE SUM(BUFFERS)

        ---------- ---------- ------------

        DEFAULT          8192         8958

        KEEP             8192         1996

        DEFAULT         16384          252

        RECYCLE          8192         1996  

 

    4.獲得單個物件佔用buffer cache的比率

 

            SELECT round(obj_cnt/totalcache_cnt*100,3)

            FROM

                (SELECT COUNT(*) AS obj_cnt

                FROM v$bh

                WHERE objd=(

                      SELECT data_object_id 

                      FROM Dba_Objects

                      WHERE object_name=UPPER('big_table')

                        AND owner='SCOTT'))a,  

                (SELECT NAME

                       ,block_size

                       ,SUM(buffers) AS totalcache_cnt

                       ,COUNT(*)

                FROM v$buffer_pool

                    WHERE NAME='DEFAULT'

                GROUP BY NAME,block_size

                HAVING SUM(buffers)>0) b;          

 

            ROUND(OBJ_CNT/TOTALCACHE_CNT*100,3)

            -----------------------------------

                                           .015

                                          

七、查詢不同的buffer pool的命中率(buffer cache hit ratio)

    ratio並不能表明增加cache size可以提高效能。高ratio有時反而會讓你誤認為cache size已經足夠大而滿足要求了。比如:重複的掃描

    一些大表或索引。然後大表的全表掃描往往都是物理讀,會人為的降低hit ratio。因此在不同高峰時段,多次採集資料非常有必要(或使用

    StatsPack

    Db_cache_size 是針對預設的db_block_size的,對於非標準的block,要特別指定DB_nK_CACHE_SIZE 引數。

   

        SELECT NAME,

               block_size,

               physical_reads,

               db_block_gets,

               consistent_gets,

               (1 -(physical_reads / (DECODE(db_block_gets, 0, 1, db_block_gets) +

               DECODE(consistent_gets, 0, 1, consistent_gets)))) * 100  "Hit Ratio"

        FROM   V$BUFFER_POOL_STATISTICS

        ORDER  BY NAME;

 

        NAME       BLOCK_SIZE PHYSICAL_READS DB_BLOCK_GETS CONSISTENT_GETS Hit Ratio

        ---------- ---------- -------------- ------------- --------------- ---------

        DEFAULT         16384             63             5             128    52.632

        DEFAULT          8192          21013        230479          879158    98.106

        KEEP             8192              0             0               0   100.000

        RECYCLE          8192            106             0             434    75.632

   

八、總結

        儘管使用不同的緩衝池從某種程度上來說可以大大提高資料庫系統的I/O,給予了DBA更多的選擇性。然而,多個緩衝池(buffer pool)

    增加了管理的複雜度,其次由於不同的緩衝池不能夠共享,在某種程度上來說,勢必造成buffer cache大小的浪費。因此,如果default

    buffer pool能夠滿足現有的需求,儘可能的避免使用過多的緩衝池帶來管理的不便。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22578826/viewspace-703517/,如需轉載,請註明出處,否則將追究法律責任。

相關文章