木曜日, 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%'

テーブル縮小

■自動拡張されたテーブルスペースをどこまで縮小可能か?
-- 9i以上用
SELECT FILE_NAME, ((E.BLOCK_ID - 1) * T.BLOCK_SIZE + E.BYTES) / 1024 BYTE_K
FROM DBA_TABLESPACES T,DBA_DATA_FILES D,(
SELECT
DISTINCT
FILE_ID
,TABLESPACE_NAME
,MAX(BLOCK_ID) OVER (PARTITION BY FILE_ID) BLOCK_ID
,FIRST_VALUE(BYTES) OVER (PARTITION BY FILE_ID ORDER BY BLOCK_ID
DESC) BYTES
FROM DBA_EXTENTS
WHERE TABLESPACE_NAME = UPPER('&&TSNAME')
) E
WHERE T.TABLESPACE_NAME = D.TABLESPACE_NAME
AND D.TABLESPACE_NAME = E.TABLESPACE_NAME
AND D.FILE_ID = E.FILE_ID
AND T.TABLESPACE_NAME = UPPER('&&TSNAME')
;

-- 8i用
SELECT D.NAME, ((E.BLOCK_ID - 1) * D.BLOCK_SIZE + E.BYTES) /1024 BYTE_K
FROM DBA_TABLESPACES T,V$DATAFILE D,DBA_EXTENTS E
WHERE D.FILE# = E.FILE_ID
AND T.TABLESPACE_NAME = E.TABLESPACE_NAME
AND T.TABLESPACE_NAME = UPPER('&&TSNAME')
AND (E.FILE_ID,E.BLOCK_ID) IN (
SELECT FILE_ID,MAX(BLOCK_ID)
FROM DBA_EXTENTS S
WHERE T.TABLESPACE_NAME = S.TABLESPACE_NAME
GROUP BY FILE_ID)
;

一時表領域

■一時表領域について

●V$SORT_USAGE
ソート状況の確認が出来る。

SELECT * FROM V$SORT_USAGE;

SELECT SID,OSUSER,MACHINE,BLOCKS,PROGRAM
FROM V$SESSION A,V$SORT_USAGE B
WHERE A.SADDR = B.SESSION_ADDR
ORDER BY BLOCKS DESC;

SELECT USER,B.SQL_TEXT,SUM(BLOCKS)
FROM V$SORT_USAGE A,V$SQLTEXT B
WHERE A.SQLADDR=B.ADDRESS
AND SQLHASH=B.HASH_VALUE
GROUP BY USER,B.SQL_TEXT;

●V$SORT_SEGMENT
SELECT * FROM V$SORT_SEGMENT;

●V$TEMPSEG_USAGE
SELECT * FROM V$TEMPSEG_USAGE;

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

SQL>

●DBA_TEMP_FILES
SELECT * FROM DBA_TEMP_FILES;

*********************************************
●V$SORT_USAGE
SELECT * FROM V$SORT_USAGE;

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

SQL>

SELECT TABLESPACE_NAME, BYTES, BLOCKS, MAXBYTES, MAXBLOCKS, USER_BYTES, USER_BLOCKS
FROM DBA_TEMP_FILES;

TABLESPACE_NAME BYTES BLOCKS MAXBYTES MAXBLOCKS USER_BYTES USER_BLOCKS
------------------------------ ---------- ---------- ---------- ---------- ---------- -----------
TEMP 5242880000 640000 0 0 5241831424 639872

SQL>

■一時表領域の再作成
----------------------------------------
次のファイルを作成します。
DELTEMP.SQL及びCREATETEMP.SQLをREPTEMP.BATと
同一パスに配置し、バッチファイルを実行します。

※パス及びサービス名、ファイルサイズ等は使用環境に従い修正します。


SQLPLUS /NOLOG @DELTEMP.SQL
DEL D:\ORACLE\ORADATA\TEMP01.DBF
SQLPLUS /NOLOG @CREATETEMP.SQL
DEL D:\ORACLE\ORADATA\TEMPX01.DBF


SET ECHO ON
CONNECT SYS/CHANGE_ON_INSTALL@???? AS SYSDBA
CREATE TEMPORARY TABLESPACE TEMPX
TEMPFILE 'D:\ORACLE\ORADATA\TEMPX01.DBF' SIZE 10M;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMPX;
DROP TABLESPACE TEMP;
EXIT


SET ECHO ON
CONNECT SYS/CHANGE_ON_INSTALL@???? AS SYSDBA
CREATE TEMPORARY TABLESPACE TEMP
TEMPFILE 'D:\ORACLE\ORADATA\TEMP01.DBF' SIZE 40M REUSE AUTOEXTEND ON
NEXT 640K MAXSIZE UNLIMITED;
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP;
DROP TABLESPACE TEMPX;
EXIT

メモリ

■メモリ

各メモリーの大きさの妥当性を監視
1 共有プール(SHARED_POOL_SIZE)
. ライブラリ・キャッシュ
. ディクショナリキャッシュ
2 データベースバッファキャッシュ(DB_BLOCK_BUFFERS)
3 REDOログ・バッファ(LOG_BUFFER)

●ライブラリ・キャッシュ
select sum(reloads)/sum(pins) from v$librarycache;

SUM(RELOADS)/SUM(PINS)
----------------------
.002784741
reload率が1%を上回る場合は、初期化パラメータSHARED_POOL_SIZEの値を増やす

●ディクショナリキャッシュ
select sum(getmisses)/sum(gets) from v$rowcache;

SUM(GETMISSES)/SUM(GETS)
------------------------
.016589166

ミス率が10~15%を上回る場合は、初期化パラメータSHARED_POOL_SIZEの値を増やす

●データベースバッファキャッシュ(DB_BLOCK_BUFFERS)
データベース・バッファ・キャッシュのヒット率の計算:
1 - (physical reads)/( db block gets + consistent gets )
データディクショナリ v$sysstatの項目
physical reads:48
db block gets:41
consistent gets:44
select 1 - (physicalreads.value)/(dbblockgets.value + consistentgets.value) as buffercache_hit_raito
from
(select value from v$sysstat where STATISTIC# = 48) physicalreads,
(select value from v$sysstat where STATISTIC# = 41) dbblockgets,
(select value from v$sysstat where STATISTIC# = 44) consistentgets

BUFFERCACHE_HIT_RAITO
---------------------
.976029012

ヒット率が 60 ~ 70 % (90%以下の方がよい?)を下回る場合は、初期化パラメータDB_BLOCK_BUFFERSの値を増やす

●ユーザグローバル領域で最大メモリを消費しているユーザを検索
SELECT USERNAME, SUM(VALUE) "TOTAL UGA MEMORY(BYTES)"
FROM V$SESSION SE, V$SESSTAT ST, V$STATNAME NM
WHERE SE.SID = ST.SID
AND ST.STATISTIC# = NM.STATISTIC#
AND NM.NAME = 'session uga memory max'
GROUP BY USERNAME;