今天在給客戶數據庫做檢查的時候發現了一些TOP SQL,其執行的消耗如下所示:


10天內,執行了2526萬多次,在我取快照的5個小時內,執行了200多萬次,CPU的消耗就占用了執行時間的95%,有沒有什么辦法還能夠提速呢,因為是個40多條數據的小表,走索引也不見得會提升多少。那么有沒有別的辦法能夠提速呢。

這個時候經同事提點,想到了result_cache。想要用的爽6好,那么首先我們得搞清楚result_cache的概念。
result cache 在SGA中或者是客戶端應用內存中占用的一塊區域,它存儲著數據庫查詢或者查詢塊的結果以供重復使用。緩存的行在SQL語句與session之間是共享的,除非是緩存失效。
有兩種類型的結果緩存:1、服務器結果緩存。2、客戶端結果緩存。
服務器結果緩存:它屬于SGA中的shared pool共享池,在這里面存放的是SQL查詢結果與PLSQL函數返回的結果。
使用服務器結果緩存的優勢:OLAP應用程序從中受益頗高,訪問大量的行但是返回了少量的結果就非常適合結果緩存,像數據倉庫。例如,查詢重寫等價與創建了一個物化視圖來存放查詢結果緩存,代替了表。
工作原理:
當你執行一個查詢的時候,數據庫會在內存中查找是否已經存在了結果緩存中。如果存在,則數據庫代替查詢直接從內存返回結果。如果不存在,則數據庫執行查詢,返回輸出結果,并將結果存儲至結果緩存中。
當用戶重復執行查詢或函數時候,數據庫將會從緩存中檢索行,減少響應時間。當該依賴的對象被修改的話,緩存的結果將會無效。
下面我將用例子進行對比,對照組為:第一次執行,重復執行,加hint執行,加hint重復執行

邏輯讀:5740,物理讀:5731

邏輯讀:5740

加了hint第一次執行,邏輯讀:5740

加了hint重復執行
最終發現,結果集緩存生效的時候,查詢直接返回結果,連邏輯讀都沒了。這將大幅度提升重復執行的SQL的效率。當然


我針對表temp進行了一個更新操作,來看看結果緩存是否還有效。結果發現,表temp發生了修改結果緩存就失效了,查詢的時候又進行了一次結果緩存操作。
查看視圖V$RESULT_CACHE_OBJECTS
SELECT id, type, creation_timestamp, block_count,
column_count, pin_count, row_count
FROM V$RESULT_CACHE_OBJECTS
WHERE cache_id = '6f5h95tbubjc49ntyvtmcwu707';

在視圖中如果使用呢,比如用一個常見的with as語句進行實驗。

然后用常用的view實驗

客戶端結果緩存:
通過應用程序OCI接口,將SQL查詢的結果緩存放在了客戶端進程使用的內存中。該客戶端結果緩存存在于每個進程,并且進程內的所有session共享。ORACLE官方建議客戶端結果緩存針對于那些只讀或者以讀為主的表使用。
使用客戶端結果緩存的優勢:
OCI驅動程序,像OCCI、JDBC OCI驅動程序和ODP.NET,支持客戶端結果緩存。使用客戶端結果緩存的性能優勢包括:
1、減少查詢響應時間
當重復執行查詢時,應用程序會直接從客戶端緩存中檢索結果,從而加快查詢響應時間。
2、更有效的利用數據庫資源。
減少服務器往返可能會大大節省服務器資源(如服務器CPU和I/O)的性能。節省出來的資源可以給其他的任務,從而使服務器更具擴展性。
3、降低內存花費
The result cache uses client memory, which may be less expensive than server memory
這個結果緩存使用的是客戶端內存,多半比服務器內存便宜。
工作原理:
客戶端結果緩存存儲最外層查詢的結果,即OCI應用程序定義的列。子查詢和查詢塊不會被緩存。
如下圖,展示了一個帶有數據庫登錄會話的客戶端進程。此客戶端進程在客戶端進程中運行的多個應用程序會話之間共享一個客戶端結果緩存。如果第一個應用程序會話運行查詢,那么它會從數據庫中檢索行,并將它們緩存在客戶機結果緩存中。如果其他應用程序會話運行相同的查詢,那么它們也會從客戶端結果緩存中檢索行。



客戶端結果緩存透明地使結果集與影響它的會話狀態或數據庫更改保持一致。當事務更改用于構建緩存結果的數據庫對象的數據或元數據時,數據庫會在下一次到服務器的往返過程中向OCI客戶端發送一個結果緩存失效。




