ORACLE性能優化- Buffer cache 的調整與優化


Buffer Cache是SGA的重要組成部分,主要用於緩存數據塊,其大小也直接影響系統的性能。當Buffer Cache過小的時候,將會造成更多的

free buffer waits事件。 下面將具體描述Buffer Cache的作用,調整與優化。

一、SGA的所有組件

    從動態視圖v$sga_dynamic_components獲取SGA的相關信息

 

        SELECT component, current_size, min_size FROM v$sga_dynamic_components;

        COMPONENT                 CURRENT_SIZE   MIN_SIZE

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

        shared pool                   71303168   71303168

        large pool                     4194304    4194304

        java pool                      4194304    4194304

        streams pool                   4194304    4194304

        DEFAULT buffer cache         113246208  113246208

        KEEP buffer cache                    0          0

        RECYCLE buffer cache                 0          0

        DEFAULT 2K buffer cache              0          0

        DEFAULT 4K buffer cache              0          0

        DEFAULT 8K buffer cache              0          0

        DEFAULT 16K buffer cache             0          0

        DEFAULT 32K buffer cache             0          0

        ASM Buffer Cache                     0          0

 

二、Buffer cache介紹

    1.Buffer cache的類型通常包括

        default buffer cache

        keep buffer cache

        recycle buffer cache

        nk buffer caches

        與Buffer cache打交道的后台進程為DBWn,與之對應的數據文件通常位於system 表空間,sysaux表空間,undo表空間,datafile 等  

        Buffer cache是SGA的一部分,其內容是由用戶進程從數據文件讀取出來的數據塊,並且所有的用戶共享這些數據塊。通常,服務

        器進程為提高I/O性能,會一次性讀多個數據塊。對於Buffer cache中的臟數據則由DBWn進程寫入到數據文件。同樣為提高性能,DBWn

        進程也會一次寫多個數據塊。Buffer cache會擁有一個數據塊的多個副本,當前塊的最新副本僅有一份,而該數據塊老的或舊的副本可

        能有多份,用於塊的讀一致性。Buffer cache采用LRU算法來淘汰掉過時的數據塊。

            Buffer cache中存在檢查點隊列以及LRU鏈表。

 

    2.Buffer cache的幾個相關參數

        Buffer cache能有由多個獨立的且具有不同block size的緩沖池(buffer pool)組成。

        DB_BLOCK_SIZE:參數決定了數據庫主塊的塊大小,該塊的大小通常被系統表(system,sysaux)空間和主要的Buffer cache(recycle,keep,

            default buffer cache)所使用決定主要的Buffer cache大小的幾個參數

            db_cache_size

            db_keep_cache_size

            db_recycle_cache_size

 

    3.Buffer cache中塊的四種狀態

        pinned:意味着多個會話在相同的時段寫同一個數據塊,其他的會話等待訪問塊。

        clean:優先要淘汰掉的數據塊,即不是pinned狀態,也不會被再次使用的塊.該塊可能和磁盤上的塊處於同步狀態,也可能是一個讀一致性塊

        free/unused:即Buffer cache中的塊處於空閑狀態或未使用狀態,通常是由於實例剛剛啟動。

        dirty:已發生變化的數據塊,且沒有進程再使用該塊,則在aged out之前需要立即由DBWn 寫入到數據文件。

            服務器進程將數據塊從數據文件填充到Buffer cache,當Buffer cache中不再需要使用到數據塊的副本時,而DBWn進程則將臟數據

        寫入到數據文件,用於將數據塊由  pinned 狀態變為free 狀態。

    4.參數db_block_checksum

        該參數設置為true,則一個指定的校驗碼被同時寫入到數據塊,用於防止磁盤,I/O系統損壞導致數據的丟失。

三、客戶端服務器進程從Buffer cache獲取數據的過程

    1.服務器進程使用一個哈希函數來檢查所需的數據塊是否已經位於Buffer cache。如果在Buffer cache中找到所需的數據塊,則該塊根據使

        用的頻率放置到LRU隊列中特定的位置。此時的讀數據塊為邏輯讀,且不在需要執行后續步驟。如果不在Buffer cache中,則轉到下一步。

    2.服務器進程搜索LRU列表中是否存在可用的空閑空間存放新的數據塊。在搜索LRU列表同時時,已經被修改的臟數據將被服務器進程放置到

        檢查點隊列。

    3.檢查點隊列長度超出預設大小的闕值或服務器進程搜索空閑塊操作預設的次數(由隱藏參數_db_block_max_scan_pct所指定的值,表示已

        經掃描的buffer header數量占整個LRU鏈表上的buffer header的總數量,在i中該限定值為40%),則服務器進程通過DBWn將臟數據從

        Buffer cache寫出到數據文件。

    4.當可用的空閑塊被找到后,服務器進程從數據文件讀入塊到Database Buffer cache並放置到LRU隊列中。如果所得到的塊不是一致性讀塊

        ,則服務器進程從undo segment中重構一致性塊。

    Buffer cache與DBWn密切相關,下面給出DBWn觸發的條件

        臟緩沖列表達到指定的闕值大小

        搜索LRU空閑隊列達到預設的闕值次數

        發生檢查點事件

        數據庫關閉時

        表空間實現熱備份時

        表空間離線

        在段被刪除時

       

四、對buffer cache調優,命中率等

    1.調整buffer cache調優規則

        調優的目標:盡可能在Buffer cache中找到數據,降低等待可用空閑塊的時間

        調試方法:

            wait events

            cache hit ration

            v$db_cache_advice view

        調整手段

            降低SQL命令對數據塊的請求,如避免使用select * from 語句

            增加緩沖池的大小

            不同訪問方式使用不同的緩沖池(buffer pools)

            緩存常用的表到內存

            並行讀或排序操作不使用cache,直接從磁盤讀入到PGA及內存

 

    2.決定Buffer cache的幾個指標

        下面的查詢中列出了涉及到buffer cache的幾個重要指標數

      SELECT NAMEVALUE    FROM   v$sysstat

            WHERE  NAME IN ('session logical reads',

                            'physical reads',

                            'physical reads direct',

                            'physical reads direct (lob) ',

                            'consistent gets',

                            'db block gets',

                            'free buffer inspected',

                            'free buffer requested',

                            'dirty buffers inspected',

                            'pinned buffers inspected');   

            NAME                                   VALUE

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

            session logical reads           139150060175

            db block gets                      274690511

            consistent gets                 139129962467

            physical reads                   21335058151

            free buffer requested            21085155516

            dirty buffers inspected               156801

            pinned buffers inspected              432841

            free buffer inspected                 968639

            physical reads direct                4995527

                       

        Session Logical Reads:所有的邏輯讀的數據塊的數量。

       

        Free Buffer Inspected指標:

            為尋找空閑buffer之前所檢查塊的總數量,即跳過塊的數量。如果該值接近臟數據塊的數量,則表明空閑塊很少,該值應盡可能小

            於臟塊的數量。

           

        Free Buffer Waits:

            當session在LRU list上沒有尋找到空閑可用數據塊或者搜尋可用的內存數據塊被暫停的時候,該發生該事件,此為等待DBWn將臟

            塊寫入到數據文件的等待數。除此之外,會話在做一致性讀時,需要構造數據塊在某個時刻的前映像(image),此時需要申請內

            存來存放這些新構造的數據塊,如果內存中無法找到這樣的內存塊,也會發生這個等待事件。

           

        Buffer Busy Waits:

            用戶服務器進程已找到所需的數據塊,但該塊正被其它進程使用或多個進程同時要修改該塊,此時需要等待的時間。

            當一個會話需要讀取一個數據塊,但這個數據塊正在被另一個會話讀取到內存中時,此時同樣發生Buffer Busy Waits事件。

 

     SELECT event        ,total_waits

            FROM v$system_event

            WHERE event IN ('free buffer waits','buffer busy waits');  

            EVENT                     TOTAL_WAITS

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

            buffer busy waits            35216021  

           

        查詢event事件名稱

      SELECT NAME       ,parameter1

                   ,parameter2

                   ,parameter3

            FROM v$event_name

            WHERE NAME='buffer busy waits';

            NAME                           PARAMETER1           PARAMETER2           PARAMETER3

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

            buffer busy waits              file#                block#               id

 

        產生Buffer busy waits的幾種情形

            DATA BLOCK,數據塊的競爭,該情形通常是基於表段和索引段上的競爭,下面的處理辦法

                盡可能縮小SQL語句的查詢字段,查詢范圍,如不使用select * 查詢,將like子句改為直接賦值等

                檢查索引的合理性。如使用了sequence生成的索引,其索引鍵通常位於相同的塊,因此可以使用反向索引避免此問題

                使用自動段空間管理或增加空閑列表,以避免多個進程同時插入相同的塊

                查詢視圖v$session_wait來獲得熱點塊的文件ID,塊ID,通過這些信息來獲得對象ID,進一步對該對象進行調整

            UNDO Header

                基於UNDO段頭部的競爭,如果未使用自動撤銷段管理模式,則需要增加更多的回滾段

            UNDO BLOCK

                基於UNDO段塊的競爭,如果未使用自動撤銷段管理模式,則需為回滾段分配更大的尺寸

               

        產生Free Buffer waits的幾種情形    

            DBWn進程來不及將數據寫入到數據文件,導致需要等待被釋放的空間

            I/O系統速度過於緩慢

                確保數據庫文件是否分布在不同的磁盤上,或增加更高性能的磁盤

            資源等待造成I/O系統過慢,如latch等待

                確保數據庫文件是否分布在不同的磁盤上,或增加更高性能的磁盤

            Buffer cache太小,導致DBWn來不及將臟數據寫入到數據文件

                需要增大buffer cache的尺寸

            Buffer cache太大,而單一的DBWn進程需要多次才能將數據寫入到文件

                減少buffer cache的尺寸,或增加更多的DBWn進程

       

    3.評估Cache的命中率

        計算命中率的思想

            1-(物理讀的次數-總的請求次數)

       

            計算命中率

         SELECT ROUND(1 ((physical.value - direct.value - lobs.value/ logical.value),3*100 ||'%'

                       "Buffer Cache Hit Ratio"

                FROM   v$sysstat physical,

                       v$sysstat direct,

                       v$sysstat lobs,

                       v$sysstat logical

                WHERE  physical.name 'physical reads'

                       AND direct.name 'physical reads direct'

                       AND lobs.name 'physical reads direct (lob)'

                       AND logical.name 'session logical reads';

           

        physical reads

            從Oracle級別來理解,從磁盤讀數據塊的次數,一次可以讀多塊,由參數db_file_multiblock_read_count來控制。此種讀方式使用

            了db cache.

            形象示意:db_file ==> db_cache ==> pga

 

        physical reads direct

            有些數據塊不會先從硬盤讀入內存再從內存讀入PGA再傳給用戶,而是繞過SGA直接從硬盤讀入PGA。比如並行查詢以及從臨時表空

            間讀取數據。這部分數據塊由於不緩存使得hit ratio不會被提高。其在計算hit ratio時應當被扣除。

            形象示意:db_file  ==> pga

                通常,disk sort / hash exp direct=Y ,都會有physical reads direct

           

        scott@ORCL>  select name from v$statname where statistic# in (54,55,56);

            NAME

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

            physical reads

            physical reads cache            --使用buffer cache

            physical reads direct           --不使用buffer cache

 

        physical reads direct (lob)

            對於大值對象,如LOB數據類型以及LOB段,Oracle可以繞過buffer cache而直接使用PGA,其原理等同於physical reads direct

           

        使用physical reads direct,physical reads direct (lob)的優點:

            對於一個大操作,需要請求大量數據塊,假設又使用並行執行,且執行次數就那么一次,這個時候就適合使用direct方式,

            如果還是走buffer cache則需要把buffer cache里已緩存的數據庫都清空

            注意physical write /direct 同理

 

        session logical reads

            發出的總的請求次數,此處是指從database buffer cache中請求塊。對於一致性讀,則這些緩沖包含來自回滾段的數據

 

        下面是另一種不同的計算命中率的方法,通常用在10g和11g之中

    SELECT NAME,         physical_reads,

                   db_block_gets,

                   consistent_gets,

                   ROUND((1 (physical_reads (db_block_gets + consistent_gets))) * 100|| '%' ratio

            FROM   V$BUFFER_POOL_STATISTICS

            WHERE  NAME 'DEFAULT';

            SELECT (1 (SUM(decode(NAME'physical reads'VALUE, 0)) /

                   (SUM(DECODE(NAME'db block gets'VALUE, 0)) +

                   SUM(DECODE(NAME'consistent gets'VALUE, 0))))) * 100 "Hit Ratio"

            FROM   v$sysstat;

 

            consistent gets from cache

                在回滾段Buffer中的數據構造一致性讀數據塊的總次數。其產生原因是由於其他會話對當前數據塊進行操作,如update操作,

                但是由於我們的查詢是在這些修改之前調用的,所以需要使用回滾段中的數據塊的前映像進行查詢,來保證數據的一致性。

                這樣就產生了一致性讀。

               

            db block gets     

                在操作中提取的塊數目,而不是在一致性讀的情況下而產生的塊數。

                當前塊(current,相對於cosistent讀而言,current總是最新的塊),從buffer cache中請求的次數。當前塊意思就是在操作

                中正好提取的塊數目,而不是在一致性讀的情況下而產生的塊數。通常的情況下,一個查詢提取的塊是在查詢開始的那個時

                間點上存在的數據塊,當前塊是在這個時刻存在的數據塊,而不是在這個時間點之前或者之后的數據塊數目。

 

            physical reads cache   

                從磁盤讀入到buffer cache中的總次數。

                產生的主要原因是:在數據庫高速緩存中不存在這些塊, 全表掃描, 磁盤排序等

 

                db_block_gets + consistent_gets兩者之和作為總的請求次數,在與physical_reads相比進而得到命中率

 

            此方法與前面命中率計算的方法不一樣,更簡單直觀。

 

    4.影響命中率的因素

        全表掃描(小標尚可,對於大表而言I/O性能更差。而且全表掃描總是被置於LRU的最尾端,隨時被aged out)

        不同數據定義和應用程序設計影響命中率

        大表的隨機訪問(非順序)

        不均衡的cache hit

       

        命中率需要考慮的問題

            a.對相同的大表和索引的重復掃描容易造成命中率很高的假象。定期檢查頻繁使用且返回結果集很大的SQL語句,確保這些SQL語

                句使用了最優的執行計划。

            b.避免返回查詢相同的數據,盡可能將獲得的結果集緩存的客戶端程序或中間件。

            c.大表的全表掃描問題,直接將其放置到LRU的尾端,容易aged out。

                (小表通常指全表掃描時占用buffer cache 20%或擁有個數據塊)。

            d.對較大OLTP系統而言,表中的很多行僅僅被訪問次或很少的次數,基於此,這些塊不易長時間占住buffer cache。

            f.對於並行查詢或排序等,持續增加buffer cache的大小並無實際意義,優化效果並明顯。

 

    5.下列情形可以考慮增加buffer cache

        一些等待事件已經被優化

        不良的SQL語句已經被優化

        操作系統級別無不良的內存頁面置換

        上次增加的buffer cache有效

        基於上面的情形,且命中率很低,此時可以增加buffer cache

       

    6.增加buffer cache 的步驟

        首先將db_cache_advice置於ON 狀態

        檢查動態性能視圖v$db_cache_advice(需要考慮增加后不影響操作系統級別過多的內存頁面置換)

        動態增加db_cache_size的值(生產數據庫不建議關閉系統而使用動態調整alter system set db_cache_size=nM;)

   

        查看當前buffer cache的大小

     SELECT NAME,current_size,buffers FROM v$buffer_pool;

            NAME                           CURRENT_SIZE    BUFFERS

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

            DEFAULT                                3456     428760     

           

    7.減少buffer cache 的情形

        在命中率很高的情形下,查詢視圖v$db_cache_advice,來權衡適度降低buffer cache size是否會使得系統I/O顯劇增加,如不是,且

        降低buffer cache size不會影響性能的情況下,則可以適度降低buffer cache size的大小。

        使用alter system set db_cache_size來調整

 

    8.使用advisor來調整buffer cache

        buffer cache advisor 可以啟用或禁用通過收集統計信息來預估buffer cache的大小,然后根據預估的大小以及工作負荷來調整buffer

        cache的大小。buffer cache advisor功能通過設置參數db_cache_advice 開啟用或禁用,該參數僅能支持系統級別的修改。

        其參數值為:OFF,ON,READY

            OFF:禁用buffer cache advisor特性,且不為advisor分配內存

            READY:不收集數據,但是收集數據的內存已經預先分配好了.通過把參數值從off設置為ready,然后再設置為on,以避免出現錯誤。

                ALTER SYSTEM SET db_cache_advice ON | READY OFF ;

   

        該參數設置的前提條件為STATISTICS_LEVEL參數必須要先設置為TYPICAL或者ALL

       

        通過設置啟用buffer cache advisor 功能后,可以查看視圖v$db_cache_advice來獲得不同負荷下的advisor

        以下是該視圖的幾個重要列

            SIZE_FOR_ESTIMATE

            BUFFERS_FOR_ESTIMATE

            ESTD_PHYSICAL_READS

       

        查看缺省的buffer cache的advice

            SELECT size_for_estimate "Cache Size (MB)",

                   size_factor,

                   buffers_for_estimate    "Buffers",

                         estd_physical_read_factor est_read_factor,

                   estd_physical_reads     estd_phy_red

                   -- ,estd_physical_read_time est_phy_red_t   --此參數在i 中不可用

            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');   

                   

            Cache Size (MB) SIZE_FACTOR    Buffers EST_READ_FACTOR ESTD_PHY_RED

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

             352       .1019      43670         15.8455   6.1906E+10

             704       .2037      87340         58.5913   2.2891E+11

             1056       .3056     131010         31.6149   1.2351E+11

             1408       .4074     174680         21.5397   8.4152E+10

             1760       .5093     218350         14.6721   5.7321E+10

             2112       .6111     262020          8.3646   3.2679E+10

             2464        .713     305690          3.8134   1.4898E+10

             2816       .8148     349360          1.9615   7663197796

             3168       .9167     393030          1.2403   4845534681

             3456        1       428760             1   3906820053

             3520      1.0185     436700           .9675   3779821439

             3872      1.1204     480370           .8359   3265831355

             4224      1.2222     524040           .7512   2934896434

             4576      1.3241     567710           .6957   2717876216

             4928      1.4259     611380           .6565   2564852647

             5280      1.5278     655050           .6272   2450487527

             5632      1.6296     698720           .6045   2361720470

             5984      1.7315     742390           .5859   2289177246

             6336      1.8333     786060           .5726   2236962972

             6688      1.9352     829730           .5619   2195121418

             7040       2.037     873400           .5521   2156817317

                   

    9.優化Buffer cache的常用參數及視圖

        db_cache_size

        db_cache_advice

        db_keep_cache_size

        db_recycle_cache_size

        db_file_multiblock_read_count

        statspace report

        v$db_cache_advice(view)

 

        視圖

            v$buffer_pool_statistics

            v$buffer_pool

            v$db_cache_advice

            v$sysstat

            v$sesstat

            v$system_event

            v$session_wait

            v$bh

            v$cache

10.oracle的一個重要的發展方向就是自動管理,當然,SGA與PGA也不例外。

從oracle9i開始,就出現了一個新的參數SGA_MAX_SIZE,可以保證在此數值之內的內存可以自由地修改和調配。

如指定了SGA_MAX_SIZE,就可以在這個指定范圍內自由地設置SHARED POOL,DATA BUFFER等的大小。

 

從oracle10g開始,又出現了另外一個新的參數,SGA_TARGET,只要設置了這個參數,所有的SGA的組建,如SHARED POOL,DATA BUFFER,LARGE POOL等,都不需要手動

指定了,oracle會自動管理。這一特性被稱為自動共享內存管理(Atuomatic Shared Memory Management,ASMM)

也就是說,oracle會根據需要隨時改變各個內存組建的大小,以達到最佳使用狀態。

但這個參數的最大值會受到SGA_MAX_SIZE值的限制。關閉自動管理,只需要將這個SGA_TARGET參數設置為0

 

另外,如果我們想設置SGA_MAX_SIZE值的大小還需要受到MEMORY的限制,如果MEMORY_MAX_TARGET的值已經和SGA_MAX_SIZE的值相同了,那么我們如果直接擴大SGA_MAX_SIZE則會導致oracle重啟后無法打開。

SPFILE文件損壞。那么我們只能通過PFILE文件來恢復SPFILE了,同時設置的內容也沒有了。

所以我們需要先看MEMORY_MAX_TARGET和MEMORY_TARGET,並設置的更大,當然需要復合硬件的實際。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM