2010年9月21日 (火)

続・Client result cache (クライアント結果キャッシュ) #1 w

最終回とおまけで終了させてしまったので、”続”にしてみたw


まずは、Oracle11 r2のマニュアル(原文)を。(Oracle11g r1でも同じなので)

2

マニュアルには、シノニム経由の場合、クライアント結果キャッシュされないという記載はない…

ところが…

デモプログラムでアクセスするqctable表をOCITESTユーザではなくSCOTTユーザに作成し
パブリックシノニムを経由してOCITESTユーザからアクセスするよう環境を変更し〜て〜み〜る〜と〜


なんと〜〜〜〜〜〜〜〜クライアント結果キャッシュ対象外になるではありませんか〜〜〜。:)

なぜ、この手の見つけるとニッコリしちゃうんでしょw

11:21:52 SYS> conn ocitest/ocitest
接続されました。
11:22:23 OCITEST> drop table qctable purge;

表が削除されました。

経過: 00:00:00.55
11:22:33 OCITEST> desc qctable
ERROR:
ORA-04043: オブジェクトqctableは存在しません。


11:24:32 OCITEST> conn scott/tiger
接続されました。
11:26:50 SCOTT> CREATE TABLE qctable (empno NUMBER, ename VARCHAR2(20), sal NUMBER);

表が作成されました。

経過: 00:00:00.16
11:26:57 SCOTT> conn / as sysdba
接続されました。
11:27:39 SYS> grant select, insert, delete, update on scott.qctable to ocitest;

権限付与が成功しました。

経過: 00:00:00.03
11:27:54 SYS> create public synonym qctable for scott.qctable;

シノニムが作成されました。

経過: 00:00:00.12
11:28:15 SYS> conn ocitest/ocitest
接続されました。
11:29:30 OCITEST> desc qctable
名前 NULL? 型
----------------------------------------- -------- ----------------------------
EMPNO NUMBER
ENAME VARCHAR2(20)
SAL NUMBER

11:29:33 OCITEST> exec insert_val;

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.36
11:29:39 OCITEST> commit;

コミットが完了しました。

経過: 00:00:00.01
11:29:41 OCITEST>

という準備の後に、前回改造した(オリジナルのcdemoqc.cでも確認できます。)デモプログラムを実行中にclient_result_cache_stats$ビュ−を覗いて見ると〜

シノニム経由だとキャッシュされなくなることが確認できる。


11:33:22 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
140 1 Block Size 256
140 2 Block Count Max 4096
140 3 Block Count Current 128
140 4 Hash Bucket Count 1024
140 5 Create Count Success 0
140 6 Create Count Failure 0
140 7 Find Count 0
140 8 Invalidation Count 0
140 9 Delete Count Invalid 0
140 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00
11:33:48 SYS>

あと一つぐらいはエントリ書くかも、(書かないかも)




Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #2
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #3
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #4
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #5 (最終回)
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #おまけ

| | コメント (0) | トラックバック (0)

2010年9月14日 (火)

Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #おまけ

前回、最終回と言っておきながらおまけを付けるのもMac De Oracle流w

client result cacheの効果を見る方法はclient_result_cache_stats$ビューだけじゃないんですよ。

おなじみのSQLトレースを使っても確認できます。

・クライアント結果キャッシュなしのSQLトレース

SQL ID: 6xq85x8zzu4wf
Plan Hash: 1630726318
SELECT empno, ename, sal
FROM
qctable


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 11 34 0 0
Execute 5 0.00 0.00 0 0 0 0
Fetch 10 0.00 0.00 6 40 0 5
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 16 0.00 0.00 17 74 0 5

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 82 (OCITEST)

Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS FULL QCTABLE (cr=8 pr=6 pw=0 time=0 us cost=3 size=12 card=1)


Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
1 TABLE ACCESS MODE: ANALYZED (FULL) OF 'QCTABLE' (TABLE)


Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 15 0.00 0.00
SQL*Net message from client 15 0.00 0.00
db file sequential read 1 0.00 0.00
db file scattered read 1 0.00 0.00


・クライアント結果キャッシュありのSQLトレース

SQL ID: 6gsb66qbaqg37
Plan Hash: 1630726318
SELECT /*+ result_cache */ empno, ename, sal
FROM
qctable


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.02 10 34 0 0
Execute 1 0.00 0.02 0 0 1 0
Fetch 2 0.00 0.00 6 8 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.04 16 42 1 1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 82 (OCITEST)

Rows Row Source Operation
------- ---------------------------------------------------
1 RESULT CACHE 35dnz5hwwxb2k5f5b2ucfcff1d (cr=8 pr=6 pw=0 time=0 us)
1 TABLE ACCESS FULL QCTABLE (cr=8 pr=6 pw=0 time=0 us cost=3 size=12 card=1)


Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT MODE: ALL_ROWS
1 RESULT CACHE OF '35dnz5hwwxb2k5f5b2ucfcff1d'
column-count=3; dependencies=(OCITEST.QCTABLE); name="SELECT /*+
result_cache */ empno, ename, sal FROM qctable"
1 TABLE ACCESS MODE: ANALYZED (FULL) OF 'QCTABLE' (TABLE)


Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 3 0.00 0.00
log file sync 1 0.00 0.00
SQL*Net message from client 3 0.00 0.00
db file sequential read 1 0.00 0.00
db file scattered read 1 0.00 0.00




Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #2
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #3
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #4
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #5 (最終回)

| | コメント (0) | トラックバック (0)

2010年9月12日 (日)

Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #5 (最終回)

これってクライアント結果キャッシュをちゃんと動作させる為じゃなく、cdemoqc.cってクライアント結果キャッシュのデモを実行した時に、別クライアントからclient_result_cache_stats$ビューの作成、参照件数等をチェックすることで動作確認できるようにするための改造なので、動作確認できたらdual表を無理矢理問い合わせるなんてぇロジック不要ですから、お間違いのないように。m(_ _)m 2010/9/13追記。

さて、Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係も今回が最終回.

最終回なのでOracleのバージョン情報も載せておきますね。

19:54:51 SYS> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE 11.1.0.7.0 Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production

経過: 00:00:00.00
19:55:56 SYS>

Client Result Cacheを有効化する為のプログラミング上のポイント!
・OCIStmtPrepare2()を使う。

マニュアルにも記載されてますが、Client Result Cacheを有効かするためにはStatement cache(文キャッシュ)を有効化している必要がある。
 OCIStmtPrepare()を使ってしまうと文キャッシュされないのでClient result cacheが効かない。

・OCIStmtFetch2()でOCI_NO_DATAまでフェッチする。

例えば、1行しかないからOCIStmtExecute()の後、OCIStmtFetch2()を1度しか行っていないと、OCI_NO_DATAが発生しないのでClient Result Cacheに問合せ結果が乗らない。

その他、初期化パラメータや /*+ RESULT_CACHE */ ヒントを利用する等といった前提はマニュアルを読んでね。

最後に総まとめとして、cdemoqc.cを思いっきり修正し必要最低限かつ、cdemoqc.c内でclient_result_cache_stats$を確認するという怪しい作りじゃなく、別途、SQL*Plusからclient_result_cache_stats$ビューを問い合わせ、Client result cache(クライアント結果キャッシュ)が出来ているか確認できるように改造しちゃいました。

但し、削除次いでにwindows対応の部分までも削ぎ落としてしまいました。ごめんなさい。ごめんなさい。

以下、Mac De Oracle版 cdemoqc.c (除くWindows)のコード。

[oracle@lampeye demo]$ cat $ORACLE_HOME/rdbms/demo/cdemoqc.c
/* Copyright (c) 2007, Oracle. All rights reserved. */

/*
NAME
cdemoqc - Basic OCI Query Cache(result cache) functionality

DESCRIPTION
This program demonstrate the working of Query cache.
To use the query cache feature (and hence this program), database
should have been brought up with client side result cache enabled. To bring
the database with result cache enabled, add the following lines in
initialization parameter file,
client_result_cache_size=<cache size in bytes>
client_result_cache_lag=<timeout value for cache in ms>
compatible=11.0.0.0.0
and bring up the database.

*/


# include <oci.h>

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <time.h>

#include <unistd.h>

#define EMPLOYEE 0

/* Function prototypes */
static void query_tab();
static void dummy_query();
static void dbLogon();
static void dbLogoff();
static void Checkerr(OCIError *errhp, sword status, text *msg);

int main();

static sword status = 0;
static OCISvcCtx *svchp;
static OCIError *errhp;
static OCIEnv *envhp;

/* Queries with result cache hints */
static text *cache_query=
(text *)"SELECT /*+ result_cache */ empno, ename, sal FROM qctable";
//(text *)"SELECT empno, ename, sal FROM qctable";

static text *dummy= (text *)"SELECT COUNT(*) FROM DUAL";
/* - main -------------------------------------------------------------------*/
int main ()
{
long t;
time(&t);
printf ("Start -- %s",ctime(&t));
printf ("Query cache is enabled by using result_cache hints\n\n");

/* Logging on to multiple sessions */
dbLogon ();

printf ("Employee: Execute will fetch rows from server\n");
query_tab(EMPLOYEE);
printf ("\n\nEmployee: Execute will fetch rows from local cache, 4 times\n");
query_tab(EMPLOYEE);
query_tab(EMPLOYEE);
query_tab(EMPLOYEE);
query_tab(EMPLOYEE);
printf ("\n\nTotal query 5 times\nSleeping...30sec..\n");
sleep(30);
time(&t);
dummy_query(EMPLOYEE);
printf("dummyクエリ実行済み、10秒待機中。\n");
printf("この間にclient_result_cache_stats$ビューを他端末からチェック!\n\n%s",
ctime(&t));
sleep(10);

dbLogoff ();
return 0;
}

static void dummy_query ()
{
OCIStmt *stmthp = (OCIStmt *)0;
OCIDefine *def1hp = (OCIDefine *)0;
ub4 ctr;
sb4 ctrSz = sizeof(ctr);
ub2 datelen=0;
ub4 prefetch = 0;

Checkerr (errhp,
OCIStmtPrepare2 ((OCISvcCtx *)svchp,(OCIStmt **)&stmthp,
(OCIError *)errhp, (text *)dummy, (ub4)strlen((char *)dummy),
(oratext *)NULL, (ub4) 0, (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT),
(oratext *)"OCIStmtPrepare");

/* Setting the prefetch count = 0 */
Checkerr(errhp,
OCIAttrSet((OCIStmt *) stmthp, OCI_HTYPE_STMT, (dvoid *)&prefetch,
sizeof(prefetch), OCI_ATTR_PREFETCH_ROWS, (OCIError *)errhp),
(oratext *) "OCIAttrSet-prefetch");

Checkerr (errhp,
OCIDefineByPos ((OCIStmt *)stmthp, (OCIDefine **)&def1hp,
(OCIError *)errhp, (ub4)1, (dvoid *)&(ctr), (sb4)ctrSz, (ub2)SQLT_INT,
(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT),
(oratext *)"OCIDefByPos");

if ((status = OCIStmtExecute ((OCISvcCtx *)svchp, (OCIStmt *)stmthp,
(OCIError *)errhp, (ub4)0, (ub4)0, (OCISnapshot *)0,
(OCISnapshot *)0, (ub4)OCI_DEFAULT)) != OCI_SUCCESS )
{
printf ("OCIStmtExecute for Query Dual - Fail\n" );
Checkerr (errhp, status,(oratext *)"Stmt Execute");
}
else
{
status = OCIStmtFetch2((OCIStmt *)stmthp, (OCIError *)errhp, (ub4)1,
(ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT);

if (status == OCI_ERROR || status == OCI_INVALID_HANDLE)
{
Checkerr(errhp, status, (oratext *)"OCIStmtFetch2");
return;
}
else if (status != OCI_NO_DATA)
{
printf("Dual selected.\n");
}
}

Checkerr (errhp,
OCIStmtRelease ((OCIStmt *)stmthp, (OCIError *)errhp,(dvoid *)NULL, 0,
OCI_DEFAULT), (oratext *)"StmtRelease");
}

/* - Logon to the DB in two sessions ----------------------------------------*/
static void dbLogon ()
{
ub4 cachesize=10;
OraText *connStr = (text *)"";
OraText *username = (text *)"ocitest";
OraText *password = (text *)"ocitest";
OCIAuthInfo *authhp = (OCIAuthInfo *)0;

OCIEnvCreate ((OCIEnv **)&envhp, (ub4)OCI_DEFAULT, (dvoid *)0,
(dvoid * (*)(dvoid *, size_t))0,
(dvoid * (*)(dvoid *, dvoid *, size_t))0,
(void (*)(dvoid *, dvoid *))0, (size_t)0, (dvoid **)0);

OCIHandleAlloc ((dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR,
(size_t) 0, (dvoid **) 0);

OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&authhp,
(ub4)OCI_HTYPE_AUTHINFO, (size_t)0, (dvoid **)0);

OCIAttrSet ((dvoid *)authhp, (ub4)OCI_HTYPE_AUTHINFO, (dvoid *)username,
(ub4)strlen((char *)username), (ub4)OCI_ATTR_USERNAME,
(OCIError *)errhp);

OCIAttrSet ((dvoid *)authhp, (ub4)OCI_HTYPE_AUTHINFO, (dvoid *)password,
(ub4)strlen((char *)password), (ub4)OCI_ATTR_PASSWORD,
(OCIError *)errhp);

Checkerr (errhp,
OCISessionGet ((OCIEnv *)envhp, (OCIError *)errhp,
(OCISvcCtx **)&svchp, (OCIAuthInfo *)authhp, (OraText *)connStr,
(ub4)strlen((char *)connStr), (OraText *)NULL, (ub4)0, (OraText **)0,
(ub4 *)0, (boolean *)0,(ub4)OCI_DEFAULT),
(oratext *)"OCISessionGet");

printf ("Connected to Employee Session\n");

OCIAttrSet((dvoid *)svchp, OCI_HTYPE_SVCCTX, (dvoid *)&cachesize,
(ub4)0,OCI_ATTR_STMTCACHESIZE,errhp);

}

/* - Execute SQL query and prints the data ----------------------------------*/
static void query_tab ()
{
OCIStmt *stmthp = (OCIStmt *)0;
OCIDefine *def1hp = (OCIDefine *)0;
OCIDefine *def2hp = (OCIDefine *)0;
OCIDefine *def3hp = (OCIDefine *)0;
ub4 empno;
text ename[100];
ub4 sal;
sb4 empnoSz = sizeof (empno);
sb4 enameSz = sizeof (ename);
sb4 salSz = sizeof (sal);
ub2 datelen=0;
ub4 prefetch = 0;

Checkerr (errhp,
OCIStmtPrepare2 ((OCISvcCtx *)svchp,(OCIStmt **)&stmthp,
(OCIError *)errhp, (text *)cache_query, (ub4)strlen((char *)cache_query),
(oratext *)NULL, (ub4) 0, (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT),
(oratext *)"OCIStmtPrepare");

/* Setting the prefetch count = 0 */
Checkerr(errhp,
OCIAttrSet((OCIStmt *) stmthp, OCI_HTYPE_STMT, (dvoid *)&prefetch,
sizeof(prefetch), OCI_ATTR_PREFETCH_ROWS, (OCIError *)errhp),
(oratext *) "OCIAttrSet-prefetch");

Checkerr (errhp,
OCIDefineByPos ((OCIStmt *)stmthp, (OCIDefine **)&def1hp,
(OCIError *)errhp, (ub4)1, (dvoid *)&(empno), (sb4)empnoSz, (ub2)SQLT_INT,
(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT),
(oratext *)"OCIDefByPos");

Checkerr (errhp,
OCIDefineByPos ((OCIStmt *)stmthp, (OCIDefine **)&def2hp,
(OCIError *)errhp, (ub4)2, (dvoid *)&(ename), (sb4)enameSz, (ub2)SQLT_STR,
(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT),
(oratext *)"OCIDefByPos2");

Checkerr (errhp,
OCIDefineByPos ((OCIStmt *)stmthp, (OCIDefine **)&def3hp,
(OCIError *)errhp, (ub4)3, (dvoid *)&(sal), (sb4)salSz, (ub2)SQLT_INT,
(dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)OCI_DEFAULT),
(oratext *)"OCIDefByPos3");

if ((status = OCIStmtExecute ((OCISvcCtx *)svchp, (OCIStmt *)stmthp,
(OCIError *)errhp, (ub4)0, (ub4)0, (OCISnapshot *)0,
(OCISnapshot *)0, (ub4)OCI_DEFAULT)) != OCI_SUCCESS )
{
printf ("OCIStmtExecute for SELECT - Fail\n" );
Checkerr (errhp, status,(oratext *)"Stmt Execute");
}
else
{
do
{
status = OCIStmtFetch2((OCIStmt *)stmthp, (OCIError *)errhp, (ub4)1,
(ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT);

if (status == OCI_ERROR || status == OCI_INVALID_HANDLE)
{
Checkerr(errhp, status, (oratext *)"OCIStmtFetch2");
break;
}
else if (status != OCI_NO_DATA)
{
printf("\nEMPNO is %d, ENAME is %s, SAL is %d\n", empno, ename, sal);
}
}while(status != OCI_NO_DATA);
}

Checkerr (errhp,
OCIStmtRelease ((OCIStmt *)stmthp, (OCIError *)errhp,(dvoid *)NULL, 0,
OCI_DEFAULT), (oratext *)"StmtRelease");
}

/* - Session Logoff --------------------------------------------------------*/
static void dbLogoff ()
{
printf ("\nLogging off the connected session.\n");

Checkerr (errhp,
OCISessionRelease(svchp, errhp, 0,0, OCI_DEFAULT),
(oratext *) "Session-Release");
}

/* - Error checking routing -------------------------------------------------*/
void Checkerr(OCIError *errhp, sword status, text *msg)
{
text msgbuf[512];
sb4 errcode = 0;

memset((void *) msgbuf, (int)'\0', (size_t)512);
if(status!=OCI_SUCCESS)
{
printf("error msg: %s\n",msg);
}

switch (status)
{
case OCI_SUCCESS: break;
case OCI_SUCCESS_WITH_INFO:
printf("status = OCI_SUCCESS_WITH_INFO\n");
OCIErrorGet((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode,
msgbuf, (ub4) sizeof(msgbuf), (ub4) OCI_HTYPE_ERROR);
printf("ERROR CODE = %d\n", errcode);
printf("%.*s\n", 512, msgbuf);
if (errcode == 436 || errcode == 437 || errcode == 438 || errcode == 439)
exit(1);
break;
case OCI_NEED_DATA:
printf("status = OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
printf("status = OCI_NO_DATA\n");
break;
case OCI_ERROR:
printf("status = OCI_ERROR\n");
OCIErrorGet((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode,
msgbuf, (ub4) sizeof(msgbuf), (ub4) OCI_HTYPE_ERROR);
printf("ERROR CODE = %d\n", errcode);
printf("%.*s\n", 512, msgbuf);
if (errcode == 436 || errcode == 437 || errcode == 438 || errcode == 439)
exit(1);
break;
case OCI_INVALID_HANDLE:
OCIErrorGet((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode,
msgbuf, (ub4) sizeof(msgbuf), (ub4) OCI_HTYPE_ERROR);
printf("ERROR CODE = %d\n", errcode);
printf("%.*s\n", 512, msgbuf);
printf("status = OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
printf("status = OCI_STILL_EXECUTE\n");
break;
case OCI_CONTINUE:
printf("status = OCI_CONTINUE\n");
break;
default:
break;
}
return;
}


64bit 環境なので以下のように demo_rdbms64.mkでmakeしま〜す。


[oracle@lampeye demo]$ make -f demo_rdbms64.mk build EXE=cdemoqc OBJS="cdemoqc.o"
/usr/bin/gcc -fPIC -c -I/opt/u01/app/oracle/product/11.1.0/db_1/rdbms/demo
-I/opt/u01/app/oracle/product/11.1.0/db_1/rdbms/public
-I/opt/u01/app/oracle/product/11.1.0/db_1/plsql/public -I/opt/u01/app/oracle/product/11.1.0/db_1/network/public
-I/opt/u01/app/oracle/product/11.1.0/db_1/precomp/public cdemoqc.c -DLINUX -DORAX86_64 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1
-D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS -DLONG_IS_64 -DSS_64BIT_SERVER
/usr/bin/gcc -L/opt/u01/app/oracle/product/11.1.0/db_1/lib/
-L/opt/u01/app/oracle/product/11.1.0/db_1/rdbms/lib/ -o cdemoqc cdemoqc.o -lclntsh
`cat /opt/u01/app/oracle/product/11.1.0/db_1/lib/sysliblist` -ldl -lm -lpthrea


実行!!! 同一表(1行だけ登録されてます)を5回問合せ、うち4回はClient result cacheにヒットさせます。
Sleeping...30sec..の待機は、オリジナルのコードでは60秒待機させていましたが私の環境だと30秒待機でOKでした。
dummyクエリ実行済み、10秒待機中。のメッセージが表示されたら、予め起動していたSQL*Plusからclient_result_cache_stats$を問い合わせます。クライアント結果キャッシュが効いているか確認できるはずです。

[oracle@lampeye demo]$ ./cdemoqc
Start -- Thu Sep 9 19:54:09 2010
Query cache is enabled by using result_cache hints

Connected to Employee Session
Employee: Execute will fetch rows from server

EMPNO is 1, ENAME is EMP_1, SAL is 900


Employee: Execute will fetch rows from local cache, 4 times

EMPNO is 1, ENAME is EMP_1, SAL is 900

EMPNO is 1, ENAME is EMP_1, SAL is 900

EMPNO is 1, ENAME is EMP_1, SAL is 900

EMPNO is 1, ENAME is EMP_1, SAL is 900


Total query 5 times
Sleeping...30sec..
Dual selected.
dummyクエリ実行済み、10秒待機中。
この間にclient_result_cache_stats$ビューを他端末からチェック!

Thu Sep 9 19:54:39 2010

Logging off the connected session.
[oracle@lampeye demo]$

SQL*Plusからの確認!

・デモプログラム起動直後の状態
19:39:02 SYS> select * from client_result_cache_stats$;

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
111 1 Block Size 0
111 2 Block Count Max 0
111 3 Block Count Current 0
111 4 Hash Bucket Count 0
111 5 Create Count Success 0
111 6 Create Count Failure 0
111 7 Find Count 0
111 8 Invalidation Count 0
111 9 Delete Count Invalid 0
111 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

この間にclient_result_cache_stats$ビューを他端末からチェック!が表示された時点の状態
19:54:13 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
111 1 Block Size 256
111 2 Block Count Max 4096
111 3 Block Count Current 128
111 4 Hash Bucket Count 1024
111 5 Create Count Success 1
111 6 Create Count Failure 0
111 7 Find Count 4
111 8 Invalidation Count 0
111 9 Delete Count Invalid 0
111 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

・デモプログラム終了直後の状態
19:54:40 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.00




Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #2
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #3
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #4

| | コメント (0) | トラックバック (0)

2010年9月11日 (土)

Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #4

前回のつづきです。


前回は、OCIStmtPreare2()まで実行させた。
OCIStmtExecute()かOCIStmtFetch2()が実行されたタイミングでclient_result_cache_stats$ビューへ該当クライアントから統計情報がアップされているように見える! という動きは確認。

今回は、OCIStmtExecute()まで実行させ、OCIStmtFetch2()をコメントアウトしてみた。

[oracle@lampeye demo]$ diff $ORACLE_HOME/rdbms/demo/cdemoqc.c.org $ORACLE_HOME/rdbms/demo/cdemoqc.c
138d137
< /*
144d142
< */
431,452c429,450
< else
< {
< printf("Contents of CLIENT_RESULT_CACHE_STATS$\n");
< printf("STAT_ID NAME OF STATISTICS VALUE CACHE_ID\n");
< printf("======= ================== ===== ========\n");
< do
< {
< status = OCIStmtFetch2((OCIStmt *)stmthp, (OCIError *)errhp, (ub4)1,
< (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT);
<
< if (status == OCI_ERROR || status == OCI_INVALID_HANDLE)
< {
< Checkerr(errhp, status, (oratext *)"OCIStmtFetch2");
< break;
< }
< else if (status != OCI_NO_DATA)
< {
< printf("%5d %-20s %8d %6d\n", statid, name, value, cacheid);
< }
< }while(status != OCI_NO_DATA);
<
< }
---
> // else
> // {
> // printf("Contents of CLIENT_RESULT_CACHE_STATS$\n");
> // printf("STAT_ID NAME OF STATISTICS VALUE CACHE_ID\n");
> // printf("======= ================== ===== ========\n");
> // do
> // {
> // status = OCIStmtFetch2((OCIStmt *)stmthp, (OCIError *)errhp, (ub4)1,
> // (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT);
> //
> // if (status == OCI_ERROR || status == OCI_INVALID_HANDLE)
> // {
> // Checkerr(errhp, status, (oratext *)"OCIStmtFetch2");
> // break;
> // }
> // else if (status != OCI_NO_DATA)
> // {
> // printf("%5d %-20s %8d %6d\n", statid, name, value, cacheid);
> // }
> // }while(status != OCI_NO_DATA);
> //
> // }
457a456,458
> printf("Sleep 10sec...\n");
> sleep (10);
>
[oracle@lampeye demo]$

mekeして実行!!!

[oracle@lampeye demo]$ ./cdemoqc
Query cache is enabled by using result_cache hints

Connected to Employee Session
Connected to HR Session

Employee: Execute will fetch rows from server
Employee: Execute will fetch rows from local cache
HR: Execute will cause a roundtrip during first execute, but the same result
set created in Employee Session will be shared thereafter
HR: Execute will fetch rows from local cache

HR: Updating the table

Employee: Execute will fetch rows from server and hence the local result set
will be updated
HR: Execute will fetch rows from updated local cache
Employee: Execute will fetch rows from local cache

Sleeping for few seconds to let the stat table to get updated

Please enter password for sys user to continue:
xxxxxxxx!
Sleep 10sec...

Logging off all the connected sessions.
[oracle@lampeye demo]$

やった〜〜〜、見えた〜〜〜〜〜。OCIStmtExecute()が実行され、その要求がサーバまで到達する場合に、client_result_cache_stats$へ統計情報が反映されているように見える。
(ちなみに、ログは載せていないが、sleep(60)待機後、もう一度、クライアント結果キャッシュ対象のクエリを実行しても別クライアントからclient_result_cache_stats$から統計情報を参照することはできなかった)

・デモプログラム実行前の状態
21:59:31 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.00

・デモプログラム実行直後の状態
21:59:32 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
116 1 Block Size 0
116 2 Block Count Max 0
116 3 Block Count Current 0
116 4 Hash Bucket Count 0
116 5 Create Count Success 0
116 6 Create Count Failure 0
116 7 Find Count 0
116 8 Invalidation Count 0
116 9 Delete Count Invalid 0
116 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

・Please enter password for sys user to continue:が表示され、待機している状態
21:59:36 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
116 1 Block Size 0
116 2 Block Count Max 0
116 3 Block Count Current 0
116 4 Hash Bucket Count 0
116 5 Create Count Success 0
116 6 Create Count Failure 0
116 7 Find Count 0
116 8 Invalidation Count 0
116 9 Delete Count Invalid 0
116 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

・Sleep 10sec...が表示され10秒待機している状態
22:00:54 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
116 1 Block Size 256
116 2 Block Count Max 4096
116 3 Block Count Current 128
116 4 Hash Bucket Count 1024
116 5 Create Count Success 2
116 6 Create Count Failure 0
116 7 Find Count 4
116 8 Invalidation Count 1
116 9 Delete Count Invalid 0
116 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

・デモプログラム終了直後の状態
22:01:00 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.00
22:01:23 SYS>

次回へつづく〜。




Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #2
・Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #3

| | コメント (0) | トラックバック (0)

Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #3

前回のつづきです。

前回は、print_stats()のOCIStmtRelease()とOCISessionEnd()の間にsleepを追加し、sleepしている間(つまり、OCISessionEnd()が実行される前であれば、client_result_cache_stats$ビューに反映されたクライアント結果キャッシュの統計情報が参照できることを確認したところまでだった。

今回は、さらに掘り下げてみます。OCISessionEnd()で統計情報が破棄されるので、破棄されるタイミングは分りました。が、では、その統計情報は、どのタイミングで反映されるのでしょう。
ログはありませんが、cdemoqc.cにもともと実装されているsleep(60)をsleep(180)としても、他のクライアントの別セッションからclient_result_cache_stats$の統計情報を除いて覗いても反映されることはありませんでした。

いままでの結果から、sleep(60)〜OCISessionEnd()の間行われているということは想像できます。ということで、OCIStmtExecute()とOCIStmtFetc2()部分をコメントアウトし、OCIStmtPrepare2()だけ実行される状態にしてみました。

[oracle@lampeye demo]$ diff $ORACLE_HOME/rdbms/demo/cdemoqc.c.org $ORACLE_HOME/rdbms/demo/cdemoqc.c
138d137
< /*
144d142
< */
423,452c421,450
< if ((status = OCIStmtExecute ((OCISvcCtx *)syssvchp, (OCIStmt *)stmthp,
< (OCIError *)errhp, (ub4)0, (ub4)0,
< (OCISnapshot *)0, (OCISnapshot *)0,
< (ub4)OCI_DEFAULT)) != OCI_SUCCESS )
< {
< printf ("OCIStmtExecute for SELECT - Fail\n" );
< Checkerr (errhp, status,(oratext *)"Stmt Execute");
< }
< else
< {
< printf("Contents of CLIENT_RESULT_CACHE_STATS$\n");
< printf("STAT_ID NAME OF STATISTICS VALUE CACHE_ID\n");
< printf("======= ================== ===== ========\n");
< do
< {
< status = OCIStmtFetch2((OCIStmt *)stmthp, (OCIError *)errhp, (ub4)1,
< (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT);
<
< if (status == OCI_ERROR || status == OCI_INVALID_HANDLE)
< {
< Checkerr(errhp, status, (oratext *)"OCIStmtFetch2");
< break;
< }
< else if (status != OCI_NO_DATA)
< {
< printf("%5d %-20s %8d %6d\n", statid, name, value, cacheid);
< }
< }while(status != OCI_NO_DATA);
<
< }
---
> // if ((status = OCIStmtExecute ((OCISvcCtx *)syssvchp, (OCIStmt *)stmthp,
> // (OCIError *)errhp, (ub4)0, (ub4)0,
> // (OCISnapshot *)0, (OCISnapshot *)0,
> // (ub4)OCI_DEFAULT)) != OCI_SUCCESS )
> // {
> // printf ("OCIStmtExecute for SELECT - Fail\n" );
> // Checkerr (errhp, status,(oratext *)"Stmt Execute");
> // }
> // else
> // {
> // printf("Contents of CLIENT_RESULT_CACHE_STATS$\n");
> // printf("STAT_ID NAME OF STATISTICS VALUE CACHE_ID\n");
> // printf("======= ================== ===== ========\n");
> // do
> // {
> // status = OCIStmtFetch2((OCIStmt *)stmthp, (OCIError *)errhp, (ub4)1,
> // (ub2)OCI_FETCH_NEXT, (sb4)0, (ub4)OCI_DEFAULT);
> //
> // if (status == OCI_ERROR || status == OCI_INVALID_HANDLE)
> // {
> // Checkerr(errhp, status, (oratext *)"OCIStmtFetch2");
> // break;
> // }
> // else if (status != OCI_NO_DATA)
> // {
> // printf("%5d %-20s %8d %6d\n", statid, name, value, cacheid);
> // }
> // }while(status != OCI_NO_DATA);
> //
> // }
457a456,458
> printf("Sleep 10sec...\n");
> sleep (10);
>
[oracle@lampeye demo]$

makeして実行!!!!!

[oracle@lampeye demo]$ ./cdemoqc
Query cache is enabled by using result_cache hints

Connected to Employee Session
Connected to HR Session

Employee: Execute will fetch rows from server
Employee: Execute will fetch rows from local cache
HR: Execute will cause a roundtrip during first execute, but the same result
set created in Employee Session will be shared thereafter
HR: Execute will fetch rows from local cache

HR: Updating the table

Employee: Execute will fetch rows from server and hence the local result set
will be updated
HR: Execute will fetch rows from updated local cache
Employee: Execute will fetch rows from local cache

Sleeping for few seconds to let the stat table to get updated

Please enter password for sys user to continue:
xxxxxxxx!
Sleep 10sec...

Logging off all the connected sessions.
[oracle@lampeye demo]$

Sleep 10sec...中に、他クライアントからclient_result_cache_stats$ビューを覗いて見ると…

お〜〜〜〜〜〜〜〜〜〜〜〜〜、一度も統計情報が反映されません!!!!! ;)

・デモプログラム実行前の状態
21:52:37 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.01


・デモプログラム実行直後の状態

21:52:39 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
115 1 Block Size 0
115 2 Block Count Max 0
115 3 Block Count Current 0
115 4 Hash Bucket Count 0
115 5 Create Count Success 0
115 6 Create Count Failure 0
115 7 Find Count 0
115 8 Invalidation Count 0
115 9 Delete Count Invalid 0
115 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00


・Please enter password for sys user to continue:が表示されている時点の状態
21:52:44 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
115 1 Block Size 0
115 2 Block Count Max 0
115 3 Block Count Current 0
115 4 Hash Bucket Count 0
115 5 Create Count Success 0
115 6 Create Count Failure 0
115 7 Find Count 0
115 8 Invalidation Count 0
115 9 Delete Count Invalid 0
115 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

・Sleep 10sec...が表示されている時点の状態
21:53:44 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
115 1 Block Size 0
115 2 Block Count Max 0
115 3 Block Count Current 0
115 4 Hash Bucket Count 0
115 5 Create Count Success 0
115 6 Create Count Failure 0
115 7 Find Count 0
115 8 Invalidation Count 0
115 9 Delete Count Invalid 0
115 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00
21:53:52 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
115 1 Block Size 0
115 2 Block Count Max 0
115 3 Block Count Current 0
115 4 Hash Bucket Count 0
115 5 Create Count Success 0
115 6 Create Count Failure 0
115 7 Find Count 0
115 8 Invalidation Count 0
115 9 Delete Count Invalid 0
115 10 Delete Count Valid 0

10行が選択されました。

経過: 00:00:00.00

・デモプログラム終了後の状態
21:53:54 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.00
21:54:00 SYS>

徐々に、ポイントが見えてきました。次回へつづく。




Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1
Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #2

| | コメント (0) | トラックバック (0)

2010年9月10日 (金)

Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #2

前回の続きです。

最初に前回のまとめから。

client_result_cache_stats$の内容に関して以下3点が確認できました。

・client_result_cache_stats$ヘ該当クライアントから統計情報が反映されるまでタイムラグがある。
 (cdemoqc.cでは、60秒も待機してからclient_result_cache_stats$を問い合わせている)
・client_result_cache_stats$に表示されるCACHE_ID列値は、cdemoqc.cが表示している内容に一致する。
・cdemoqc.c内の別セッションを使った問い合わせでは、client_result_cache_stats$の値が取得できている。

いろいろと考え込んでいて閃いたのが、クライアント結果キャッシュってクライアントとサーバ間のラウンドトリップを減らすことも目的なわけだから、キャッシュを保持しているクライアントから、キャッシュの統計情報がサーバに渡るタイミングが非常に限られているんじゃないか……と。
ということで、クライアント結果キャッシュが効いているクエリではサーバまで行かないので、後続のOCIでサーバまで行かないと処理が終わらないタイプのOCIをコールしたついでにclient_result_cache_stats$に表示する統計情報を送るんじゃないだろーかー。ということ。

OCISessionEnd()で、統計情報が破棄されているんだろーという推測の元、クライアント結果キャッシュに載せないSQL文のPrepare,ExecuteやFetchのいずれかのタイミングで送っているんだろうという切り分けのため、print_stats()のOCIStmtRelease()とOCISessionEnd()の間にsleepを追加した。

[oracle@lampeye demo]$ diff cdemoqc.c.org cdemoqc.c
138d137
< /*
144d142
< */
457a456,458
> printf("Sleep 10sec...\n");
> sleep (10);
>
[oracle@lampeye demo]$

実行結果は以下の通り。

[oracle@lampeye demo]$ ./cdemoqc
Query cache is enabled by using result_cache hints

Connected to Employee Session
Connected to HR Session

Employee: Execute will fetch rows from server
Employee: Execute will fetch rows from local cache
HR: Execute will cause a roundtrip during first execute, but the same result
set created in Employee Session will be shared thereafter
HR: Execute will fetch rows from local cache

HR: Updating the table

Employee: Execute will fetch rows from server and hence the local result set
will be updated
HR: Execute will fetch rows from updated local cache
Employee: Execute will fetch rows from local cache

Sleeping for few seconds to let the stat table to get updated

Please enter password for sys user to continue:
xxxxxxxx
Contents of CLIENT_RESULT_CACHE_STATS$
STAT_ID NAME OF STATISTICS VALUE CACHE_ID
======= ================== ===== ========
1 Block Size 256 114
2 Block Count Max 4096 114
3 Block Count Current 128 114
4 Hash Bucket Count 1024 114
5 Create Count Success 2 114
6 Create Count Failure 0 114
7 Find Count 4 114
8 Invalidation Count 1 114
9 Delete Count Invalid 0 114
10 Delete Count Valid 0 114
Sleep 10sec...

Logging off all the connected sessions.
[oracle@lampeye demo]$


事前に起動していたSQL*Plusからclient_result_cache_stats$ビューを確認してみると…
お〜〜〜〜〜〜〜っ!、ちゃんと表示されています!!!!!。

感があたりました〜〜〜〜〜〜! :)

・cdemoqc実行前
21:41:48 SYS> select * from client_result_cache_stats$;

レコードが選択されませんでした。

・cdemoqc実行直後
経過: 00:00:00.00
21:41:49 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
114 1 Block Size 0
114 2 Block Count Max 0
114 3 Block Count Current 0
114 4 Hash Bucket Count 0
114 5 Create Count Success 0
114 6 Create Count Failure 0
114 7 Find Count 0
114 8 Invalidation Count 0
114 9 Delete Count Invalid 0
114 10 Delete Count Valid 0

10行が選択されました。


・60秒間待機している状態の時
経過: 00:00:00.00
21:41:54 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
114 1 Block Size 0
114 2 Block Count Max 0
114 3 Block Count Current 0
114 4 Hash Bucket Count 0
114 5 Create Count Success 0
114 6 Create Count Failure 0
114 7 Find Count 0
114 8 Invalidation Count 0
114 9 Delete Count Invalid 0
114 10 Delete Count Valid 0

10行が選択されました。

・cdemoqcが、client_result_cache_stats$を表示した直後の10秒待機の時
経過: 00:00:00.00
21:42:53 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
114 1 Block Size 256
114 2 Block Count Max 4096
114 3 Block Count Current 128
114 4 Hash Bucket Count 1024
114 5 Create Count Success 2
114 6 Create Count Failure 0
114 7 Find Count 4
114 8 Invalidation Count 1
114 9 Delete Count Invalid 0
114 10 Delete Count Valid 0

10行が選択されました。

・cdemoqcが終了した直後
経過: 00:00:00.00
21:42:59 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.00
21:43:09 SYS>

次回はさらに絞りこんで確認します。つづく〜




Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1

| | コメント (0) | トラックバック (0)

2010年9月 9日 (木)

Client result cache (クライアント結果キャッシュ)と client_result_cache_stats$の怪しい関係 #1

pga_aggregate_targetネタをやる予定が…client result cache(クライアント結果キャッシュ)ネタを先にやることにw

なにそれ? 美味しいのって感じの人はググって調べてもらうにしても

以下の辺りを見るとざっとなにが嬉しいのか分るかも :)
http://www.ooug.org/presentations/2010slides/Oracle_11g_Results_Cache.ppt

環境は、CentOS5.5 - Oracle11g R1 11.1.0.7.0 EEで、examplesを追加インストールして $ORACLE_HOME/rdbms/demo以下にcdemoqc.c及びcdemoqc.sqlをインストールしてあります。


あ、そうそう、今回の中心人物は、client_result_cache_stats$ビュー。クライアント結果キャッシュがどの程度効いているか客観的に判断するための統計情報が表示される。
http://download.oracle.com/docs/cd/E16338_01/server.112/b56311/statviews_2150.htm

さて、やっと本題です。

クライアント結果キャッシュがどの程度嬉しいのか確認する意味もあり、examplesをインストールして試し始めて、一番最初に悩みました。

examplesをインストールすると、クライアント結果キャッシュ用のOCIのデモプログラム cdemoqc.cを実行しても、client_result_cache_stats$ビューに該当クライアントのクライアント結果キャッシュの統計情報が表示されません。(表示されないというのは0件という意味ではなく、有るみたいなんだけど、値が0のままということなんです。見た瞬間人柱確定コースw)


クライアント結果キャッシュにクエリ結果がキャッシュされ、サーバとのラウンドトリップが無くなっているか確認したいだけなに、なんでハマるんじゃ〜w

と、叫びつつ。

cdemoqc.cのprint_stats()とその前に60秒スリープする部分のコメントを削除しました。

cdemoqc.cのオリジナルをcdemoqc.c.orgとしてdiffした結果。(とりあえず載せておきますねw)

[oracle@lampeye demo]$ diff cdemoqc.c.org cdemoqc.c
138d137
< /*
144d142
< */
[oracle@lampeye demo]$


実行した結果(makeし忘れないでね)。cdemoqc中からは60秒後にclient_result_cache_stats$の統計情報が確認できています。しか〜〜〜〜し!
(尚、事前に別xtermからSQL*Plusでsysユーザに接続、cdemoqc実行中に、client_reslut_cache_stats$ビューを確認します。)

[oracle@lampeye demo]$ ./cdemoqc
Query cache is enabled by using result_cache hints

Connected to Employee Session
Connected to HR Session

Employee: Execute will fetch rows from server
Employee: Execute will fetch rows from local cache
HR: Execute will cause a roundtrip during first execute, but the same result
set created in Employee Session will be shared thereafter
HR: Execute will fetch rows from local cache

HR: Updating the table

Employee: Execute will fetch rows from server and hence the local result set
will be updated
HR: Execute will fetch rows from updated local cache
Employee: Execute will fetch rows from local cache

Sleeping for few seconds to let the stat table to get updated

Please enter password for sys user to continue:
xxxxxxx

Contents of CLIENT_RESULT_CACHE_STATS$
STAT_ID NAME OF STATISTICS VALUE CACHE_ID
======= ================== ===== ========
1 Block Size 256 113
2 Block Count Max 4096 113
3 Block Count Current 128 113
4 Hash Bucket Count 1024 113
5 Create Count Success 2 113
6 Create Count Failure 0 113
7 Find Count 4 113
8 Invalidation Count 1 113
9 Delete Count Invalid 0 113
10 Delete Count Valid 0 113

Logging off all the connected sessions.
[oracle@lampeye demo]$

同じ時間で他のxtermの別セッションからclient_result_cache_stats$ビューを一生懸命問い合わせましたが、一度も統計情報にお目にかかれませんでした。
(以下のログからもわかるように、0件なのではなく同一CHACHE_IDの各列はリストされてはいるのですが、値が常に0のままなんです。)

・cdemoqc起動前
21:33:37 SYS> select * from client_result_cache_stats$;

レコードが選択されませんでした。

・cdemoqc起動直後
経過: 00:00:00.00
21:33:39 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
113 1 Block Size 0
113 2 Block Count Max 0
113 3 Block Count Current 0
113 4 Hash Bucket Count 0
113 5 Create Count Success 0
113 6 Create Count Failure 0
113 7 Find Count 0
113 8 Invalidation Count 0
113 9 Delete Count Invalid 0
113 10 Delete Count Valid 0

10行が選択されました。

・cdemoqc側でclient_result_cache_stats$が表示された直後
経過: 00:00:00.00
21:33:46 SYS> /

CACHE_ID STAT_ID NAME VALUE
---------- ---------- ------------------------------ ----------
113 1 Block Size 0
113 2 Block Count Max 0
113 3 Block Count Current 0
113 4 Hash Bucket Count 0
113 5 Create Count Success 0
113 6 Create Count Failure 0
113 7 Find Count 0
113 8 Invalidation Count 0
113 9 Delete Count Invalid 0
113 10 Delete Count Valid 0

10行が選択されました。

・cdemoqc正常終了後
経過: 00:00:00.00
21:35:05 SYS> /

レコードが選択されませんでした。

経過: 00:00:00.00
21:35:12 SYS>


これでは、クライアント結果キャッシュが作成され、利用されているのか判断しにくいですよね〜。なんで他プロセスの別セッションからclient_result_cache_stats$の内容が見えないのでしょう?
(cdempqc.cの作りからして、きな臭い匂いがしませんか〜w マニュアルにも書かれていないけど〜いろんな仕掛けがありそーですぞ〜。)

ということで、原因を突き止めたので、次回からじわじわ追いつめていきますw

つづく。

| | コメント (0) | トラックバック (0)