水曜日, 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

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

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

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