[20190214]11g Query Result Cache RC Latches.txt
[20190214]11g Query Result Cache RC Latches.txt
--//昨天我重復鏈接http://www.pythian.com/blog/oracle-11g-query-result-cache-rc-latches/的測試,
--//按照我的理解如果sql語句密集執行,使用Result Cache反而更加糟糕,這是我以前沒有注意到的。
--//聯想我們生產系統也存在類似的問題,我們有1個判斷連接的語句select count(*) from test_connect;
--//在業務高峰它執行可以達到1600次/秒。另外一個簡單的select sysdate from dual; 也達到800次/秒。
--//而實際上業務高峰sql語句執行率3000次/秒。這樣的2條語句就占了2400次/秒。我以前一直以為將表設置
--//為result cache,可能提高執行效率,還是通過例子測試看看。
1.環境:
SCOTT@book> @ ver1
PORT_STRING??????????????????? VERSION??????? BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx??????????? 11.2.0.4.0???? Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
SCOTT@book> show parameter job
NAME??????????????? TYPE??? VALUE
------------------- ------- ------
job_queue_processes integer 200
SCOTT@book> select * from v$latchname where name like 'Result Cache%';
LATCH# NAME????????????????????????? HASH
------ ----------------------- ----------
?? 436 Result Cache: RC Latch? 1054203712
?? 437 Result Cache: SO Latch?? 986859868
?? 438 Result Cache: MB Latch?? 995186388
--//我看到Result Cache名字與作者的不同,命名為Result Cache: RC Latch。
SCOTT@book> select name,gets from v$latch where lower(name) like '%result cache%';
NAME???????????????????????????????? GETS
------------------------------ ----------
Result Cache: RC Latch????????????????? 0
Result Cache: SO Latch????????????????? 0
Result Cache: MB Latch????????????????? 0
SCOTT@book> select count(*) from v$latch_children where lower(name) like '%result cache%';
? COUNT(*)
----------
???????? 0
--//可以注意一個細節,Result Cache沒有children latch。也僅僅1個Result Cache: RC Latch 父latch。從這里也可以看出如果
--//做了result cache的表,多個用戶并發執行,可能反而不能獲得好的性能,可能出現大量的Result Cache: RC Latch爭用的情況.
2.建立測試例子:
create table t as select rownum id from dual ;
create unique index pk_t on t(id);
--//分析略。
SCOTT@book> create table job_times ( sid?? number, time_ela number);
Table created.
--//按照源鏈接的例子修改如下:
create or replace procedure do_work(
?p_iterations in number
) is
?l_rowid? rowid;
?v_t number;
begin
?insert into job_times
? values (sys_context('userenv', 'sid'), dbms_utility.get_time)
? returning rowid into l_rowid;
?for i in 1 .. p_iterations
?loop
???? select count(*) into v_t from t;
?end loop;
?update job_times set
?? time_ela=dbms_utility.get_time-time_ela
? where rowid=l_rowid;
?commit;
end;
/
3.測試:
--//首先測試不做result cache的情況:
--//alter table t result_cache (mode default);
declare
?l_job number;
begin
?for i in 1 .. 50
?loop
? dbms_job.submit(
?? job => l_job,
?? what => 'do_work(1000000);'
? );
?end loop;
end;
/
SCOTT@book> commit ;
Commit complete.
--//注意一定要寫提交,不然dbms_job.submit要等很久才執行。
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
??????? 50??????? 9235.1??????? 461755
4.測試:
--///測試做result cache的情況,為了測試的準確,我重啟數據庫。
SCOTT@book> delete from job_times;
50 rows deleted.
SCOTT@book> commit ;
Commit complete.
SCOTT@book> alter table t result_cache (mode force);
Table altered.
--//重啟數據庫.
SCOTT@book> select name, gets, misses, sleeps, wait_time from v$latch where name like 'Result Cache%';
NAME???????????????????????????????? GETS???? MISSES???? SLEEPS? WAIT_TIME
------------------------------ ---------- ---------- ---------- ----------
Result Cache: RC Latch????????????????? 0????????? 0????????? 0????????? 0
Result Cache: SO Latch????????????????? 0????????? 0????????? 0????????? 0
Result Cache: MB Latch????????????????? 0????????? 0????????? 0????????? 0
declare
?l_job number;
begin
?for i in 1 .. 50
?loop
? dbms_job.submit(
?? job => l_job,
?? what => 'do_work(100000);'
? );
?end loop;
end;
/
SCOTT@book> commit ;
Commit complete.
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
??????? 50?????? 7135.96??????? 356798
SCOTT@book> select name, gets, misses, sleeps, wait_time from v$latch where name like 'Result Cache%';
NAME???????????????????????????????? GETS???? MISSES???? SLEEPS? WAIT_TIME
------------------------------ ---------- ---------- ---------- ----------
Result Cache: RC Latch?????????? 54232541??? 3499238????????? 0????????? 0
Result Cache: SO Latch??????????????? 202????????? 0????????? 0????????? 0
Result Cache: MB Latch????????????????? 0????????? 0????????? 0????????? 0
--//很明顯,即使存在Result Cache: RC Latch的爭用,但是WAIT_TIME=0,不過我發現這樣測試的一個缺點,就是50個job并不是同時運行.
--//$ ps -ef | grep ora_[j]|wc ,看看數量是不斷增加的過程.
--//而且采用Result Cache后效果還是增強的.
5.換一個方式測試:
SCOTT@book> delete from job_times;
53 rows deleted.
SCOTT@book> commit ;
Commit complete.
--//設置result_cache=default
SCOTT@book> alter table t result_cache (mode default);
Table altered.
$ seq 50 | xargs -I{} echo 'sqlplus -s -l scott/book <<< "execute do_work(1000000)" & '| bash
--//等全部完成...
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
??????? 50????? 10588.26??????? 529413
SCOTT@book> delete from job_times;
50 rows deleted.
SCOTT@book> commit ;
Commit complete.
--//設置result_cache=force
SCOTT@book> alter table t result_cache (mode force);
Table altered.
$ seq 50 | xargs -I{} echo 'sqlplus -s -l? scott/book <<< "execute do_work(1000000)" & '| bash
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
??????? 50?????? 8573.28??????? 428664
--//可以看到即使這樣大并發,采用result cache還是要快許多,沒有遇到作者的情況.
--//可以11GR2做了一些改進,不會遇到這樣的情況.
SCOTT@book> column name format a30
SCOTT@book> select name, gets, misses, sleeps, wait_time from v$latch where name like 'Result Cache%';
NAME???????????????????????????????? GETS???? MISSES???? SLEEPS? WAIT_TIME
------------------------------ ---------- ---------- ---------- ----------
Result Cache: RC Latch????????? 103461569??? 7263987????????? 0????????? 0
Result Cache: SO Latch??????????????? 302????????? 0????????? 0????????? 0
Result Cache: MB Latch????????????????? 0????????? 0????????? 0????????? 0
6.不過當我拿作者的最后的例子做最后的測試發現,使用result cache慢很多.
SCOTT@book> create cluster hc ( n number(*,0)) single table hashkeys 15000 size 230;
Cluster created.
SCOTT@book> create table hc_t ( n number(*,0), v varchar2(200)) cluster hc (n);
Table created.
SCOTT@book> insert into hc_t select level, dbms_random.string('p', 200) from dual connect by level <= 10000;
10000 rows created.
SCOTT@book> commit;
Commit complete.
--//分析表略.
All we need now is two procedures, one with a regular select and another with a cached select:
create or replace procedure do_hc(
?p_iterations in number
) is
?l_rowid? rowid;
?l_n number;
begin
?insert into job_times
? values (sys_context('userenv', 'sid'), dbms_utility.get_time)
? returning rowid into l_rowid;
?for i in 1 .. p_iterations
?loop
? l_n:=trunc(dbms_random.value(1, 10000));
? for cur in (select * from hc_t where n=l_n)
? loop
?? null;
? end loop;
?end loop;
?update job_times set
?? time_ela=dbms_utility.get_time-time_ela
? where rowid=l_rowid;
end;
/
Procedure created.
create or replace procedure do_rc(
?p_iterations in number
) is
?l_rowid? rowid;
?l_n number;
begin
?insert into job_times
? values (sys_context('userenv', 'sid'), dbms_utility.get_time)
? returning rowid into l_rowid;
?for i in 1 .. p_iterations
?loop
? l_n:=trunc(dbms_random.value(1, 10000));
? for cur in (select /*+ result_cache */ * from hc_t where n=l_n)
? loop
?? null;
? end loop;
?end loop;
?update job_times set
?? time_ela=dbms_utility.get_time-time_ela
? where rowid=l_rowid;
end;
/
Procedure created.
The hash cluster will go first:
SCOTT@book> delete from job_times;
4 rows deleted.
SQL> commit;
Commit complete.
declare
?l_job number;
begin
?for i in 1 .. 4
?loop
? dbms_job.submit(
?? job => l_job,
?? what => 'do_hc(100000);'
??? );
?end loop;
end;
/
PL/SQL procedure successfully completed.
SCOTT@book> commit ;
Commit complete.
--allow jobs to complete
SCOTT@book> select case grouping(sid) when 1 then 'Total:' else to_char(sid) end sid, sum(time_ela) ela from job_times group by rollup((sid, time_ela));
SID????? ELA
------- ----
41?????? 446
54?????? 437
80?????? 438
94?????? 437
Total:? 1758
--//每個測試僅僅需要4秒.
Now let's see if Result Cache can beat those numbers:
SCOTT@book> delete from job_times;
4 rows deleted.
SCOTT@book> commit ;
Commit complete.
SCOTT@book> select name, gets, misses, sleeps, wait_time from v$latch where name like 'Result Cache%';
NAME???????????????????????????????? GETS???? MISSES???? SLEEPS? WAIT_TIME
------------------------------ ---------- ---------- ---------- ----------
Result Cache: RC Latch?????????? 20385043???? 535762????????? 5???????? 94
Result Cache: SO Latch????????????????? 9????????? 0????????? 0????????? 0
Result Cache: MB Latch????????????????? 0????????? 0????????? 0????????? 0
declare
?l_job number;
begin
?for i in 1 .. 4
?loop
? dbms_job.submit(
?? job => l_job,
?? what => 'do_rc(100000);'
??? );
?end loop;
end;
/
PL/SQL procedure successfully completed.
SCOTT@book> commit ;
Commit complete.
--allow jobs to complete
SCOTT@book> select case grouping(sid) when 1 then 'Total:' else to_char(sid) end sid, sum(time_ela) ela from job_times group by rollup((sid, time_ela));
SID?????? ELA
------ ------
41?????? 3850
54?????? 3853
80?????? 3860
94?????? 3863
Total:? 15426
--//我的測試使用Result Cache 更加糟糕!!每個測試需要38秒.而作者的測試兩者幾乎差不多.作者用 Nothing (almost) 來表達.
SCOTT@book> select name, gets, misses, sleeps, wait_time from v$latch where name like 'Result Cache%';
NAME???????????????????????????????? GETS???? MISSES???? SLEEPS? WAIT_TIME
------------------------------ ---------- ---------- ---------- ----------
Result Cache: RC Latch?????????? 21768802??? 1045691???? 663187?? 64314325
Result Cache: SO Latch???????????????? 17????????? 0????????? 0????????? 0
Result Cache: MB Latch????????????????? 0????????? 0????????? 0????????? 0
--//我開始以為這里有1個將結果集放入共享池的過程,每一次執行都需要放入共享池.再次調用應該會快一些.
create or replace procedure do_rc(
?p_iterations in number
) is
?l_rowid? rowid;
?l_n number;
begin
?insert into job_times
? values (sys_context('userenv', 'sid'), dbms_utility.get_time)
? returning rowid into l_rowid;
?for i in 1 .. p_iterations
?loop
? l_n:=trunc(dbms_random.value(1, 10000));
? for cur in (select /*+ result_cache */ * from hc_t where n=l_n)
? loop
?? null;
? end loop;
?end loop;
?update job_times set
?? time_ela=dbms_utility.get_time-time_ela
? where rowid=l_rowid;
end;
/
--//再次執行:
declare
?l_job number;
begin
?for i in 1 .. 4
?loop
? dbms_job.submit(
?? job => l_job,
?? what => 'do_rc(100000);'
??? );
?end loop;
end;
/
PL/SQL procedure successfully completed.
SCOTT@book> commit ;
Commit complete.
SCOTT@book> select case grouping(sid) when 1 then 'Total:' else to_char(sid) end sid, sum(time_ela) ela from job_times group by rollup((sid, time_ela));
SID???? ELA
----- -----
72???? 3980
81???? 3900
96???? 3936
108??? 3922
Total 15738
--//問題依舊.我估計不同查詢存在select /*+ result_cache */ * from hc_t where n=l_n的情況下,探查Result Cache: RC Latch持有
--//時間很長,導致使用result cache更慢,這樣看來result_cache更加適合統計類結果不變的語句.而且綁定變量不要變化很多的情況.
--//換成普通表測試看看:
SCOTT@book> rename? hc_t to hc_tx;
Table renamed.
SCOTT@book> create table hc_t as select * from hc_tx ;
Table created.
SCOTT@book> create unique index i_hc_t on hc_t(n);
Index created.
--//分析表略.
--//調用do_hc的情況如下:
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
???????? 4???????? 431.5????????? 1726
--//調用do_rc的情況如下:
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
???????? 4?????? 4027.75???????? 16111
--//結果一樣.刪除索引在測試看看.
SCOTT@book> drop index i_hc_t ;
Index dropped.
--//調用do_hc的情況如下:
--//delete from job_times;
--//commit ;
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
???????? 4????????? 4160???????? 16640
--//調用do_rc的情況如下:
--//delete from job_times;
--//commit ;
SCOTT@book> select count(*),avg(TIME_ELA),sum(TIME_ELA) from job_times ;
? COUNT(*) AVG(TIME_ELA) SUM(TIME_ELA)
---------- ------------- -------------
???????? 4????????? 3828???????? 15312
--//這個時候result cache優勢才顯示出來.總之在生產系統使用要注意這個細節,一般result cahe僅僅只讀表(dml很少的靜態表)外.
--//如果經常使用不同變量查詢表,能使用索引的情況,使用result cache毫無優勢可言.
轉載于:https://www.cnblogs.com/lfree/p/10373399.html
總結
以上是生活随笔為你收集整理的[20190214]11g Query Result Cache RC Latches.txt的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创建Python虚拟环境——下
- 下一篇: JAVA学习知识集合