水曜日, 12月 26, 2007

表の統計データを変更する

Ask Tom "SQL Tuning"

表の統計データを変更することで、大量データを作成せず、実行計画に影響を与えることができる。

通常の統計データの取得は
exec dbms_stats.gather_table_stats (user,'t');

統計データ変更方法は

exec dbms_stats.set_table_stats( user, 'PERSON', numrows=>1000000, numblks=>100000 );

プロシージャ:set_table_statsの詳細は
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19245-01/d_stats.htm#sthref8385



金曜日, 12月 21, 2007

PL/SQLで検索結果リストをIN句に利用する

Ask Tom "varying elements in IN list"

なぜか、パッケージの中にTYPE宣言をすると、エラーになってしまうので、
仕方なく、
CREATE OR REPLACE TYPE XXXTYPE AS TABLE OF NUMBER;
で作成して、

PL/SQLでは
AND XXX_ID IN (SELECT * FROM TABLE( CAST (memberIdList AS memberIdTab)))
のようにすることで、なんとなく解決。

ちなみに、ファンクションでCURSORを返すのは、
OPEN cur1 FOR
SELECT ....
;

RETURN cur1;
ではうまくいくが、
SQLを事前に宣言してから、OPENだけで、次にRETURNしようとするとエラーになってしまう。

なぜだ。。。

木曜日, 12月 13, 2007

Tomcat 6で実現! Ajaxを超える通信技術Comet (1/3) - @IT

Tomcat 6で実現! Ajaxを超える通信技術Comet (1/3) - @IT

なかなか面白い、
通常のWEBアプリケーションでサーバー側のデータ変更をリアルタイムで更新するためには
AJAXなどを利用して、定期的にサーバーにリクエストを送るしかいないが、
Cometを利用すると、HTTPコネクションを開きぱなしにして、
サーバー側から更新データを随時送る仕組み

WEBでチャットのようなリアルタイム更新アプリケーションの実装ができるって!

1Request:1Reponseを
「プル型の通信」と言うと
こちらは
疑似的な「プッシュ型の通信」になる。

TomcatではComet実行コネクタとして、
NIO(New I/O)とAPR(Apache Portable Runtime)がある。

Tomcatのserver.xmlを修正してNIOを利用する例:

protocol="org.apache.coyote.http11.Http11NioProtocol"

リバースAjax機能はAjax+Javaをもっとやさしくする?

木曜日, 11月 29, 2007

Geekなぺーじ : 10のUNIX小技

Geekなぺーじ : 10のUNIX小技

①:複数階層のフォルダを一回で作成する。

[root@localhost ~]# mkdir -p a/b/c

[root@localhost ~]# mkdir -p a/{lib,src/doc/{html,pdf,txt}}

mkdirに-pオプションがない場合、mkdirhierを使うことが出来るらしい。
と書いてあったけど、RadhatAS4ではだめだった。
[root@localhost ~]# mkdirhier -p a/{lib,src/doc/{html,pdf,txt}}  -- NG

②:tarの解凍先を指定する。

[root@localhost ~]# tar xfv a.tar -C /tmp/a/b

③:コマンドを演算子で繋げる

一つ目のコマンドが成功した(return 0)場合にだけ実行
[root@localhost ~]# cd tmp/a/b/c && tar xvf ~/archive.tar

一つ目のコマンドが失敗した(return 0以外)場合にだけ実行
[root@localhost ~]# cd tmp/a/b/c || mkdir -p tmp/a/b/c
[root@localhost ~]# cd tmp/a/b || mkdir -p tmp/a/b && tar xvf -C tmp/a/b ~/a.tar

④:変数と「"」の組み合わせは慎重に

[root@localhost ~]#
[root@localhost ~]# ls tmp/
a b
[root@localhost ~]# VAR="tmp/*"
[root@localhost ~]# echo $VAR
tmp/a tmp/b
[root@localhost ~]# echo "$VAR"
tmp/*
[root@localhost ~]# echo $VARa

[root@localhost ~]# echo "$VARa"

[root@localhost ~]# echo "${VAR}a"
tmp/*a
[root@localhost ~]# echo ${VAR}a
tmp/a
[root@localhost ~]#

⑤:長い入力にはエスケープシーケンスを利用

[root@localhost ~]# cd tmp/a/b/c || \
> mkdir -p tmp/a/b/c && \
> tar xvf -C tmp/a/b/c ~/archive.tar

でも
[root@localhost ~]# cd tmp/a/b/c \
はNGだった。

⑥:コマンドをグループ分けする

[root@localhost ~]# ( cd tmp/a/b/c/ || mkdir -p tmp/a/b/c && \
> VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar ) \
> | mailx admin -S "Archive contents"

<>
[root@localhost ~]# { cp ${VAR}a . && chown -R guest.guest a && \
> tar cvf newarchive.tar a; } | mailx admin -S "New archive"

「{}」の前後にスペースが入るように注意しましょう。
スペースを入れないと正しく動作しないかも知れません。
また、「}」の前に来る最後のコマンドの後に「;」を入れる。

⑦:xargsをfind以外と組み合わせる

[root@localhost ~]# find 何か どこかへのパス | \
> xargs ファイル名を使う何らかのコマンド

$ xargs
a
b
c
コントロールキー+p
a b c

ファイル名を出力する他のコマンドと組み合わせる事も可能です。

$ ls | xargs
December_Report.pdf README a archive.tar mkdirhier.sh
$ ls | xargs file
December_Report.pdf: PDF document, version 1.3
README: ASCII text
a: directory
archive.tar: POSIX tar archive
mkdirhier.sh: Bourne shell script text executable

複数行を一行にまとめる事も出来ます。


$ ls -l | xargs
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 \
root root 238 Dec 03 08:19 README drwxr-xr-x 38 joe joe 354082 Nov 02 \
16:07 a -rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar -rwxr-xr-x 1 \
joe joe 3239 Sep 30 12:40 mkdirhier.sh

xargs利用上の注意

「_(アンダースコア、下棒)」はEOFとして扱われます。
そのため、その文字がxargsに渡されると、
それ以降の項目は無視されてしまいます。
この問題を回避するには-eオプションを利用してください。

⑧:grepに行数をカウントさせる

wc -l と組み合わせるのではなく、grep の-cオプションを使った方が行数の計算は速いです。

$ time grep PATTERN longfile.txt | wc -l
2811

real 0m0.097s
user 0m0.006s
sys 0m0.032s
$ time grep -c PATTERN longfile.txt
2811

real 0m0.013s
user 0m0.006s
sys 0m0.005s

grepがカウントすべきではないとき

-cオプションは、マッチした行数のみをカウントします。
-oオプションは、マッチしたパターン自体を出力します。
単一行にマッチするパターンが複数回登場する時などには、
-oオプションにより標準出力に出される行数と、
-c が行った結果のカウント数が異なってしまいます。
そのような場合には、wc -l を使いましょう。

grep -o PATTERN longfile.txt | wc -l

⑨:パターンマッチは行全体ではなくフィールドで

grepなどで行全体をマッチするのではなく、
awkで特定のフィールドを指定してパターンマッチをすべきです。

grepで行全体をマッチさせてしまうと、意図しないものも結果に入ってしまうことがあります。
例えば、ファイル更新日が12月のものを探している時に、
1月に更新したDecemberReport.pdfが結果に入ってしまう場合があります。

悪い例

ls -l | grep Dec
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf
-rw-r--r-- 1 root root 238 Dec 03 08:19 README
-rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar
良い例

ls -l | awk '$6 == "Dec"'
-rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar
-rw-r--r-- 1 root root 238 Dec 03 08:19 README

⑩:無駄なcatとパイプは行わない

grepなどのコマンドを使う時に、catをパイプで繋げてgrepの標準入力に流し込むのは無駄です。
grepなどの大抵のコマンドには、ファイル名をオプションとして渡せる機能があります。
以下に速度の比較を示します。


$ time cat longfile.txt | grep PATTERN
2811

real 0m0.015s
user 0m0.003s
sys 0m0.013s

$ time grep PATTERN longfile.txt
2811

real 0m0.010s
user 0m0.006s
sys 0m0.004s

---------------------------
いろいろ出来ますね。勉強になりました。

木曜日, 11月 08, 2007

Ask Tom "SQL Query to find gaps in date ranges"

Ask Tom "SQL Query to find gaps in date ranges"

create table t ( a int, b date, c date );

insert into t values(1, to_date( '01-jan-2007'), to_date( '15-jan-2007'));
insert into t values(2, to_date( '03-jan-2007'), to_date( '10-jan-2007'));
insert into t values(3, to_date( '12-jan-2007'), to_date( '25-jan-2007'));
insert into t values(4, to_date( '20-jan-2007'), to_date( '01-feb-2007'));
insert into t values(5, to_date( '05-feb-2007'), to_date( '10-feb-2007'));
insert into t values(6, to_date( '05-feb-2007'), to_date( '28-feb-2007'));
insert into t values(7, to_date( '10-feb-2007'), to_date( '15-feb-2007'));
insert into t values(8, to_date( '18-feb-2007'), to_date( '23-feb-2007'));
insert into t values(9, to_date( '22-feb-2007'), to_date( '16-mar-2007'));

From the above example, the gap that exists is:

02-feb-2007 --> 04-feb-2007

and we said...

Here is one approach. I used "50" - you can replace 50 with a 'better' value, or you could use

with data as (select max(c-b) c_b from t), r as (select level-1 l from data connect by level <= c_b) select .....

if you do the "data" one, you do not need the case statement as protection...

ops$tkyte%ORA10GR2> variable x number
ops$tkyte%ORA10GR2> exec :x := 50
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> with
2 r as
3 (select level-1 l
4 from dual
5 connect by level <= :x
6 )
7 select last_dt+1, dt-1
8 from (
9 select dt, lag(dt) over (order by dt) last_dt
10 from (
11 select distinct t.b+r.l dt
12 from t, r
13 where r.l <= t.c-t.b and case when t.c-t.b > :x then 1/0 end is null
14 )
15 )
16 where last_dt <> dt-1
17 /

LAST_DT+1 DT-1
--------- ---------
02-FEB-07 04-FEB-07

writing is gleaned through experience, time, effort and mentoring. Anyone can do it.



木曜日, 3月 01, 2007

ブログが正式番になったのね。

これからどんどん書き込むかね。

ただ認証キー入れるのはやっぱ面倒ね。

水曜日, 11月 29, 2006

AskTom "Update statement tuning"

AskTom "Update statement tuning"

and multi_block_read are always physical I/O?
NO!

say your multi-block read count is set reasonable (1000 isn't even borderline
reasonable), say at 64.

[quote]
but block 15, 30, and 45 are in the cache.

we'll multiblock physical IO 1..14
single block logical IO 15
multiblock physical IO 16..29

and so on.
[/quote]

土曜日, 9月 09, 2006

SQLTIP--PASCAL△

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
...
++++++++++++++++++++++++++++++++++++++++++++
SELECT EXP (SUM (LN (GREATEST (LEVEL - 1, 1))) OVER ())
/ EXP (SUM (LN (GREATEST (LEVEL - 1, 1))) OVER (ORDER BY LEVEL))
/ EXP (SUM (LN (GREATEST (&n - LEVEL, 1))) OVER (ORDER BY LEVEL DESC)) pascal
FROM DUAL
CONNECT BY LEVEL <= &n
/

SQLTIP--Fibonacci

SELECT ( POWER ((1 + SQRT (5)) / 2, LEVEL)
- POWER ((1 - SQRT (5)) / 2, LEVEL)
)
/ SQRT (5) fibonacci
FROM DUAL
CONNECT BY LEVEL <= 20
/

SELECT ( POWER ((1 + SQRT (5)) / 2, LEVEL)
- POWER ((1 - SQRT (5)) / 2, LEVEL)
)
/ SQRT (5) fibonacci,
(5 + 3 * SQRT (5)) * POWER ((1 + SQRT (5)) / 2, LEVEL)
/ 10
+ (5 - 3 * SQRT (5)) * POWER ((1 - SQRT (5)) / 2, LEVEL) / 10
- 1 sum_n
FROM DUAL
CONNECT BY LEVEL <= 20
/

SQLTIP--文字列を特定数の単語単位で改行する。

str
--------------------------------
This is not a verry long test string
Happy new year !

id string
----------------------
1 This is not a
1 verry long test
1 string
2 Happy new year
2 !


SELECT ID, STRING
FROM (SELECT level#, rnum ID,
SUBSTR (str, INSTR (str, base, 1, level#) + len,
INSTR (SUBSTR (str, INSTR (str, base, 1, level#) + len,
limit# + 1), base, -1) - 1) STRING,
INSTR (str, base, 1, level#) + len - 1 start#,
INSTR (SUBSTR (str, INSTR (str, base, 1, level#) + len,
limit# + 1), base, -1) +
INSTR (str, base, 1, level#) + len - 1 end#
FROM (SELECT LEVEL level#, limit#, base, len
FROM (SELECT MAX ( LENGTH (str)
- LENGTH (REPLACE (str, ' ')) + 1) max_part,
15 limit#, ' ' base, LENGTH (' ') len
FROM TEST)
CONNECT BY LEVEL <= max_part),
(SELECT ROWNUM rnum, ' ' || str || ' ' str,
LENGTH (str) - LENGTH (REPLACE (str, ' ')) + 1 part
FROM TEST)
WHERE level# <= part)
START WITH start# = 1
CONNECT BY PRIOR end# = start# AND PRIOR ID = ID
GROUP BY ID, level#, STRING
/

SQLTIP--任意の範囲の数値、日付を出力する。

1から100まで出力
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 100
/

20060730から20060830まで出力
SELECT (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) day#
FROM DUAL
CONNECT BY (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) <=
TO_DATE ('20060830', 'YYYYMMDD')
/

或は
SELECT *
FROM (SELECT (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) day# FROM DUAL
CONNECT BY (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) <=
TO_DATE ('20060830', 'YYYYMMDD'))
/

SQLTIP--first、lastの利用

SELECT MAX (ename) KEEP (DENSE_RANK FIRST ORDER BY sal DESC) ename, deptno,
MAX (sal) sal
FROM emp
GROUP BY deptno

SELECT MAX (ename) KEEP (DENSE_RANK LAST ORDER BY sal) ename, deptno,
MAX (sal) sal
FROM emp
GROUP BY deptno

SQLTIP--LOTO 6番号生成

SELECT MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 1, num)) no1,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 2, num)) no2,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 3, num)) no3,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 4, num)) no4,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 5, num)) no5,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 6, num)) no6
FROM (SELECT grp, num
FROM (SELECT grp, num, MOD (ROWNUM - 1, 45) + 1 rnum
FROM (SELECT CEIL (LEVEL / 45) grp,
MOD (LEVEL - 1, 45) + 1 num
FROM DUAL
CONNECT BY LEVEL <= 45 * 10
ORDER BY 1, DBMS_RANDOM.VALUE))
WHERE rnum <= 6
ORDER BY grp, num)
GROUP BY grp
/

SQLTIP--文字列から単語の数を計算

SELECT
(LENGTH ('THIS IS TEST STRING')
- LENGTH (REPLACE ('THIS IS TEST STRING', 'IS'))
)
    / LENGTH ('IS') cnt
FROM DUAL
/

SQLTIP--文字列分割

123,11,4567,8,99999,000,123456

「,」で分割

123
11
4567
...
...

SELECT SUBSTR (aa,
INSTR (aa, ',', 1, LEVEL) + 1,
INSTR (aa, ',', 1, LEVEL + 1) - INSTR (aa, ',', 1, LEVEL)
- 1
) sub
FROM (SELECT ',' || '123,11,4567,8,99999,000,123456' || ',' aa
FROM DUAL)
CONNECT BY LEVEL <= LENGTH (aa) - LENGTH (REPLACE (aa, ',')) - 1



2)
区分記号が2バイト以上の場合


SELECT SUBSTR (str,
INSTR (str, base, 1, LEVEL) + len,
INSTR (str, base, 1, LEVEL + 1)
- INSTR (str, base, 1, LEVEL)
- len
) sub
FROM (SELECT '#&&#' base, '#&&#' || '1#&(#&・#&?' || '#&&#' str,
LENGTH ('#&&#') len
FROM DUAL)
CONNECT BY LEVEL <= (LENGTH (str) - LENGTH (REPLACE (str, base))) / len - 1



3)
複数の行が存在する場合は


COL1
--------------------------------------------------
1/2/3
44/555
3/77
8/77/8


「/」 による分割


1
2
3
44
555
3
77
8
77
8

SELECT sub
FROM (SELECT DISTINCT rn, LEVEL,
SUBSTR (str,
INSTR (str, base, 1, LEVEL) + len,
INSTR (str, base, 1, LEVEL + 1)
- INSTR (str, base, 1, LEVEL)
- len
) sub
FROM (SELECT ROWNUM rn, '/' base, '/' || col1 || '/' str,
LENGTH ('/') len
FROM tab2)
CONNECT BY LEVEL <=
(LENGTH (str) - LENGTH (REPLACE (str, base)))
/ len
- 1)

SQLTIP--10進数から2進数へ、2進数から10進数へ

-- 10進数から 2進数へ
SELECT REPLACE (MAX (SYS_CONNECT_BY_PATH (bit, ',')), ',') bin
FROM (SELECT COUNT (*) OVER () - LEVEL + 1 level#,
DECODE (TRUNC (deci / POWER (2, LEVEL)),
ROUND (deci / POWER (2, LEVEL)), 0,
1
) bit
FROM (SELECT 699 deci
FROM DUAL)
CONNECT BY POWER (2, LEVEL - 1) <= deci)
START WITH level# = 1
CONNECT BY PRIOR level# = level# - 1
/

-- 2進数から 10進数へ
SELECT SUM (SUBSTR (bin, LEVEL, 1) * POWER (2, LENGTH (bin) - LEVEL)) deci
FROM (SELECT 11101 bin
FROM DUAL)
CONNECT BY LEVEL <= LENGTH (bin)
/

SQLTIP--カレンダー生成

--------------------------------------
SELECT MIN (DECODE (TO_CHAR (days, 'd'), 1, TO_CHAR (days, 'fmdd'))) 日,
MIN (DECODE (TO_CHAR (days, 'd'), 2, TO_CHAR (days, 'fmdd'))) 月,
MIN (DECODE (TO_CHAR (days, 'd'), 3, TO_CHAR (days, 'fmdd'))) 火,
MIN (DECODE (TO_CHAR (days, 'd'), 4, TO_CHAR (days, 'fmdd'))) 水,
MIN (DECODE (TO_CHAR (days, 'd'), 5, TO_CHAR (days, 'fmdd'))) 木,
MIN (DECODE (TO_CHAR (days, 'd'), 6, TO_CHAR (days, 'fmdd'))) 金,
MIN (DECODE (TO_CHAR (days, 'd'), 7, TO_CHAR (days, 'fmdd'))) 土
FROM (SELECT base_mon + LEVEL - 1 days,
( TRUNC (base_mon + LEVEL - 1, 'd')
- TRUNC (TRUNC (base_mon + LEVEL - 1, 'y'), 'd')
) / 7 + 1 week_grp
FROM (SELECT TO_DATE ('200605', 'yyyymm') base_mon
FROM DUAL)
CONNECT BY base_mon + LEVEL - 1 <= LAST_DAY (base_mon))
GROUP BY week_grp
ORDER BY week_grp
;

月 火 水 木 金 土 日
-- -- -- -- -- -- --
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

大雑把なチェックSQL

●データベースの運行状況:
select
METRIC_NAME, VALUE
from SYS.V_$SYSMETRIC
where METRIC_NAME IN ('Database CPU Time Ratio', 'Database Wait Time Ratio') AND
INTSIZE_CSEC = (select max(INTSIZE_CSEC) from SYS.V_$SYSMETRIC);

METRIC_NAME VALUE
---------------------------------------------------------------- ----------
Database Wait Time Ratio 100
Database CPU Time Ratio 0

SQL>

●前の1時間内のシステム運行状況:
SELECT TO_CHAR(END_TIME, 'YYYY-MM-DD HH:MI:SS') END_TIME, VALUE
FROM SYS.V_$SYSMETRIC_HISTORY
WHERE METRIC_NAME = 'Database CPU Time Ratio'
ORDER BY 1;

END_TIME VALUE
------------------- ----------
2006-02-20 01:38:38 3
2006-02-20 01:39:36 0
...
2006-02-20 02:38:37 0
2006-02-20 02:38:37 0

74行が選択されました。

SQL>

●データベース効率の最大値、最小値、平均値
SELECT
CASE METRIC_NAME
WHEN 'SQL Service Response Time' THEN 'SQL Service Response Time (secs)'
WHEN 'Response Time Per Txn' THEN 'Response Time Per Txn (secs)'
ELSE METRIC_NAME
END METRIC_NAME,
CASE METRIC_NAME
WHEN 'SQL Service Response Time' THEN ROUND((MINVAL / 100),2)
WHEN 'Response Time Per Txn' THEN ROUND((MINVAL / 100),2)
ELSE MINVAL
END MININUM,
CASE METRIC_NAME
WHEN 'SQL Service Response Time' THEN ROUND((MAXVAL / 100),2)
WHEN 'Response Time Per Txn' THEN ROUND((MAXVAL / 100),2)
ELSE MAXVAL
END MAXIMUM,
CASE METRIC_NAME
WHEN 'SQL Service Response Time' THEN ROUND((AVERAGE / 100),2)
WHEN 'Response Time Per Txn' THEN ROUND((AVERAGE / 100),2)
ELSE AVERAGE
END AVERAGE
FROM SYS.V_$SYSMETRIC_SUMMARY
WHERE METRIC_NAME in ('CPU Usage Per Sec',
'CPU Usage Per Txn',
'Database CPU Time Ratio',
'Database Wait Time Ratio',
'Executions Per Sec',
'Executions Per Txn',
'Response Time Per Txn',
'SQL Service Response Time',
'User Transaction Per Sec')
ORDER BY 1;

METRIC_NAME MININUM MAXIMUM AVERAGE
----------------------------------- --------- ----------- ----------
CPU Usage Per Sec 0 46 1
CPU Usage Per Txn 0 116 9
Database CPU Time Ratio 0 3 0
Database Wait Time Ratio 97 100 99
Executions Per Sec 0 5622 445
Executions Per Txn 1 25522 1880
Response Time Per Txn (secs) .18 786.18 287.54
SQL Service Response Time (secs) 0 3.24 .61
User Transaction Per Sec 0 72 1

9行が選択されました。

SQL>

●どの活動が一番時間をかかっているかを調べる。
SELECT
CASE DB_STAT_NAME
WHEN 'parse time elapsed' THEN 'soft parse time'
ELSE DB_STAT_NAME
END DB_STAT_NAME,
CASE DB_STAT_NAME
WHEN 'sql execute elapsed time' THEN TIME_SECS - PLSQL_TIME
WHEN 'parse time elapsed' THEN TIME_SECS - HARD_PARSE_TIME
ELSE TIME_SECS
END TIME_SECS,
CASE DB_STAT_NAME
WHEN 'sql execute elapsed time' THEN ROUND(100 * (TIME_SECS - PLSQL_TIME) / DB_TIME,2)
WHEN 'parse time elapsed' THEN ROUND(100 * (TIME_SECS - HARD_PARSE_TIME) / DB_TIME,2)
ELSE ROUND(100 * TIME_SECS / DB_TIME,2)
END PCT_TIME
FROM
(SELECT STAT_NAME DB_STAT_NAME, ROUND((VALUE / 1000000),3) TIME_SECS
FROM SYS.V_$SYS_TIME_MODEL
WHERE STAT_NAME NOT IN ('DB time','background elapsed time', 'background cpu time','DB CPU')),
(SELECT ROUND((VALUE / 1000000),3) DB_TIME
FROM SYS.V_$SYS_TIME_MODEL
WHERE STAT_NAME = 'DB time'),
(SELECT ROUND((VALUE / 1000000),3) PLSQL_TIME
FROM SYS.V_$SYS_TIME_MODEL
WHERE STAT_NAME = 'PL/SQL execution elapsed time'),
(SELECT ROUND((VALUE / 1000000),3) HARD_PARSE_TIME
FROM SYS.V_$SYS_TIME_MODEL
WHERE STAT_NAME = 'hard parse elapsed time')
ORDER BY 2 DESC;

DB_STAT_NAME TIME_SECS PCT_TIME
-------------------------------------------------- ---------- ----------
sql execute elapsed time 1256493.55 1.15
hard parse elapsed time 26518.525 .02
PL/SQL execution elapsed time 10944.781 .01
soft parse time 9453.695 .01
PL/SQL compilation elapsed time 4141.709 0
connection management call elapsed time 1427.068 0
sequence load elapsed time 1107.645 0
failed parse elapsed time 594.186 0
hard parse (sharing criteria) elapsed time 257.132 0
hard parse (bind mismatch) elapsed time 12.931 0
inbound PL/SQL rpc elapsed time .384 0
failed parse (out of shared memory) elapsed time 0 0
Java execution elapsed time 0 0

13行が選択されました。

SQL>

●グローバル待ち時間の長いものを探す
SELECT A.SID, B.USERNAME, A.WAIT_CLASS, A.TOTAL_WAITS,
ROUND((A.TIME_WAITED / 100),2) TIME_WAITED_SECS
FROM SYS.V_$SESSION_WAIT_CLASS A, SYS.V_$SESSION B
WHERE B.SID = A.SID AND
B.USERNAME IS NOT NULL AND
A.WAIT_CLASS != 'Idle'
ORDER BY 5 DESC;

SID USERNAME WAIT_CLASS TOTAL_WAITS TIME_WAITED_SECS
---------- ---------- --------------- ----------- ----------------
13747 E0000001 Network 14671 1493.71
13607 D0000002 User I/O 52023 382.5
13375 D0000012 User I/O 35923 173.18
13609 E0000011 Application 59 70.44
13609 E0000001 Network 3692 42.54
13512 A0000003 User I/O 7075 25.17
13461 A0000009 User I/O 2844 23.56
13617 E0000021 Network 929 16.12
13461 A0000009 Network 330656 12.89
13747 E0000021 User I/O 575 11.95
.....
13420 E0343431 Concurrency 1 0
13373 E1111111 Network 41 0
13375 D1111112 Other 30 0

139行が選択されました。

経過: 00:00:00.50
SQL>

●待ち時間履歴を調べる
SELECT
TO_CHAR(A.END_TIME,'DD-MON-YYYY HH:MI:SS') END_TIME,
B.WAIT_CLASS,
ROUND((A.TIME_WAITED / 100),2) TIME_WAITED
FROM
SYS.V_$WAITCLASSMETRIC_HISTORY A,
SYS.V_$SYSTEM_WAIT_CLASS B
WHERE
A.WAIT_CLASS# = B.WAIT_CLASS# AND
B.WAIT_CLASS != 'Idle'
ORDER BY
1, 2;

END_TIME WAIT_CLASS TIME_WAITED
----------------------- --------------- -----------
20-FEB-2006 01:38:38 Application 0
20-FEB-2006 01:38:38 Commit 4.61
20-FEB-2006 01:38:38 Concurrency 0
20-FEB-2006 01:38:38 Configuration 0
20-FEB-2006 01:38:38 Network 46.59
20-FEB-2006 01:38:38 Other 670.66
20-FEB-2006 01:38:38 System I/O 8.3
20-FEB-2006 01:38:38 User I/O 2.61
20-FEB-2006 01:39:36 Application 0
.....

XXX行が選択されました。

SQL>

●特定時間以内のI/O状況を調べる
SELECT
SESS_ID,
USERNAME,
PROGRAM,
WAIT_EVENT,
SESS_TIME,
ROUND(100 * (SESS_TIME / TOTAL_TIME),2) PCT_TIME_WAITED
FROM
(SELECT
A.SESSION_ID SESS_ID,
DECODE(SESSION_TYPE,'background',SESSION_TYPE,C.USERNAME) USERNAME,
A.PROGRAM PROGRAM,
B.NAME WAIT_EVENT,
SUM(A.TIME_WAITED) SESS_TIME
FROM
SYS.V_$ACTIVE_SESSION_HISTORY A,
SYS.V_$EVENT_NAME B,
SYS.DBA_USERS C
WHERE
A.EVENT# = B.EVENT# AND
A.USER_ID = C.USER_ID AND
-- TO_CHAR(SAMPLE_TIME, 'YYYYMMDD HH:MI:SS') > '20060101 00:00:00' AND
-- TO_CHAR(SAMPLE_TIME, 'YYYYMMDD HH:MI:SS') < '20060405 00:00:00' AND
B.WAIT_CLASS = 'User I/O'
GROUP BY
A.SESSION_ID,
DECODE(SESSION_TYPE,'background',SESSION_TYPE,C.USERNAME),
A.PROGRAM,
B.NAME
),
(SELECT
SUM(A.TIME_WAITED) TOTAL_TIME
FROM
SYS.V_$ACTIVE_SESSION_HISTORY A,
SYS.V_$EVENT_NAME B
WHERE
A.EVENT# = B.EVENT# AND
-- TO_CHAR(SAMPLE_TIME, 'YYYYMMDD HH:MI:SS') > '20060101 00:00:00' AND
-- TO_CHAR(SAMPLE_TIME, 'YYYYMMDD HH:MI:SS') < '20060405 00:00:00' AND
B.WAIT_CLASS = 'User I/O'
)
ORDER BY
6 DESC;


●待ち時間が長いSQL
SELECT
*
FROM
(SELECT
SQL_TEXT,
SQL_ID,
ELAPSED_TIME,
CPU_TIME,
USER_IO_WAIT_TIME,
ROWS_PROCESSED
FROM
SYS.V_$SQLAREA
WHERE SQL_TEXT LIKE '%DRIVING_SITE(TABLE_NAME) ORDERED%'
ORDER BY
5 DESC
)
WHERE
ROWNUM < 20
/

SQL_TEXT SQL_ID ELAPSED_TIME CPU_TIME USER_IO_WAIT_TIME
------------------------------ ------------- ------------ ---------- -----------------
select i.obj#,i.ts#,i.file#,i. 1tjnwqfpzxnng 155992860 62783286 107760000
block#,i.intcols,i.type#,i.fla
......

SELECT /*+ USE_NL (MATRIX, DAT bjadu54ff4rkq 93384393 90 89990000
A) */ MATRIX.GROUPNAME,
MATRIX.NENREI_KBN_NAME,
......

SELECT MATRIX.GROUPNAME, 9rp94fcrc2653 87619484 251 81040000
MATRIX.NENREI_KBN_NAME,
......

SELECT MATRIX.GROUPNAME, MATRI bm392979yn9jd 66626981 83061 63700000
X.NENREI_KBN_NAME, MATRIX.NENS
......

......

9行が選択されました。

経過: 00:00:00.11
SQL>

●特定SQL_IDの実行時間が長い理由を探す
SELECT
EVENT,
TIME_WAITED,
OWNER,
OBJECT_NAME,
CURRENT_FILE#,
CURRENT_BLOCK#
FROM
SYS.V_$ACTIVE_SESSION_HISTORY A,
SYS.DBA_OBJECTS B
WHERE
SQL_ID = '&SQL_ID' AND
A.CURRENT_OBJ# = B.OBJECT_ID AND
TIME_WAITED <> 0;

ブロックをを探す。

SELECT CHILD# "cCHILD"
, ADDR "sADDR"
, GETS "sGETS"
, MISSES "sMISSES"
, SLEEPS "sSLEEPS"
FROM v$latch_children
WHERE name = 'cache buffers chains' and rownum < 10
ORDER BY 5 desc, 4, 1, 2, 3;

次は、上のSQLで一番大きいSPLEEPSのADDRを利用して

column segment_name format a35
SELECT /*+ RULE */
e.owner ||'.'|| e.segment_name segment_name,
e.extent_id extent#,
x.dbablk - e.block_id + 1 block#,
x.tch,
l.child#
FROM
sys.v$latch_children l,
sys.x$bh x,
sys.dba_extents e
WHERE
x.hladdr = '&ADDR' AND
e.file_id = x.file# AND
x.hladdr = l.addr AND
x.dbablk BETWEEN e.block_id AND e.block_id + e.blocks -1
ORDER BY x.tch desc ;

col GETS format 9999999999999
select NAME, GETS, MISSES, DECODE(GETS,0,'zero',(GETS - MISSES)/GETS,'other') HIT_RATIO,
SLEEP1,DECODE(MISSES,0,'zero',SLEEP1/MISSES,'other') "SLEEPS/MISS"
from v$latch where NAME like 'cache buffer%'