Thursday, August 31, 2006

Oracle でちょっとしたパフォーマンスチェック

IBM xSeries 336 上の Oracle 10g の SqlPlus で、


select to_char(sysdate , 'YYYYMMDD HH24:MI:SS') from dual;
select 1 from dual;
-- 同じ文を 4640 個
select to_char(sysdate , 'YYYYMMDD HH24:MI:SS') from dual;


としたスクリプトを実行すると、だいたい5秒かかった。次に


select to_char(sysdate , 'YYYYMMDD HH24:MI:SS') from dual;
select 25646 from dual;
-- 同じ文を 4640 個。ただし、乱数になっている。
select to_char(sysdate , 'YYYYMMDD HH24:MI:SS') from dual;


とすると、だいたい20秒かかった。ちなみに乱数は、シェル変数の
$RANDOM を使って、シェルスクリプトで上のファイルを生成した。

SQL 文がまったく同じなら実行計画が再利用されることになるので、最初のスクリプトは5秒しかかからなかった。2番目のスクリプトは、実行計画がその都度、立案されるので時間がかかっている。

つまり、4641 件の SQL の実行計画に 15 秒かかったというわけだから、この SQL の実行計画には 3 ミリ秒ほどかかっていることになる。

実は、この実験は、いまやってる仕事で株の銘柄キーワード検索のパフォーマンスを調べる過程で実行した。MEIGARA_K_TBL に銘柄情報と、それを検索するためのキーワード(正式名称、正式カナ名称、英語名称、略称をタブ区切りにしたカラム)をセットして、


select to_char(sysdate , 'YYYYMMDD HH24:MI:SS') from dual;
SELECT SHOUKEN_CODE || '.' || MARKET_CODE
FROM MEIGARA_K_TBL
WHERE VALID_FLAG = 1 AND INSTR(KEYWORDS, 'イノテック') > 0 ORDER BY SHOUKEN_CODE;
--
-- キーワード部分を変えた文を 4640 個
--
select to_char(sysdate , 'YYYYMMDD HH24:MI:SS') from dual;


としたスクリプトを実行した。この結果はだいたい 40 秒であった。キーワードが各々異なるので実行計画はその都度、立案されていることになる。先ほどの SQL 文の実行計画を立てるのと同じだけの時間がかかっているとすると、4641 回の文字列部分一致検索に 25 秒だけかかっていることになる。

つまり、1回あたり、5 ミリ秒ほどだ。Oracle Text を使えばもっと速くなる余地はありそう。

ちなみに、部分一致検索では、LIKE 検索を使うよりは、ここでのように関数を使った方が速い。

Oracle の空文字列は NULL と見なされてしまう件

Oracle の VARCHAR2 型には問題があって、空文字列を NULL 扱いしてしまう。たとえば、


SQL> create table hoge (
2 str varchar2(88)
3 );

SQL> insert into hoge values ('');

1 row created.

SQL> select * from hoge where str = '';

no rows selected

SQL> select * from hoge where str is null;

STR
--------------------------------------------------------------------------------


SQL> create table boke (
2 str varchar2(22) not null);

Table created.

SQL> insert into hoge values ('');
insert into hoge values ('')
*
ERROR at line 1:
ORA-01400: ("TOMITA"."BOKE"."STR")にはNULLは挿入できません。



のようになってしまうのだ。これは、古くからあるバグのようで、修正するとアナウンスはされていたようだが、いまだになおっていない。

Friday, August 25, 2006

ハードディスクからのデータの完全消去

Live CD で Linux をブートして、ハードディスクを dd コマンドで書きつぶす。

df コマンドで表示される Filesystem に対して dd を実行する。たとえば、


tomita@mail:/etc$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/cciss/c0d0p3 68990656 4486156 64504500 7% /
tmpfs 1030916 0 1030916 0% /dev/shm
/dev/cciss/c0d0p1 122339 18502 97310 16% /boot
tmpfs 10240 64 10176 1% /dev


であれば、


dd if=/dev/zero of=/dev/cciss/c0d0 bs=1M


を実行すればいい。むろんスーパーユーザで実行する。こうすると、ディスクの盤面を 0x00 で埋め尽くす。

ちなみに Live CD 用のイメージをダウンロードして、それを CD に書き込むときは、イメージとして書き込まなければならない。普通に書き込むと、単なるファイルとしてイメージファイルが書き込まれてしまう。Windows なら Record Now などのツールを使わなければならない。

いまは、dd コマンドではなく shred コマンドを使った方がいい。dd と違い、ランダムな数値で書き潰してくれるので、より復元が困難になる。


shred -v -n 1 /dev/cciss/c0d0


のようにすれば、指定したデバイスをランダムな数値で1回書き潰してくれる(-n オプションで回数を指定)。回数を多くすればするほど復元しにくくなる。

Friday, August 11, 2006

XML, HTML と DTD

フォーマットが正しい XML 文書とは、開始タグが終了タグで閉じられている、属性が引用符で囲まれている、すべてのエンティティが宣言されている、などの条件を満たす文書のこと。

それとは別に、妥当な XML 文書とは、DTD を宣言し、その中で定義されているルールにしたがっている文書のことだ。

たとえば、Web アプリケーションの配備記述子である XML 文書は、次のように開始されている。


<?xml version="1.0" encoding="EUC-JP"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">


http://java.sun.com/dtd/web-app_2_3.dtd が DTD 文書である。これが、この XML 文書で使用できる合法的な構成要素を定義している。この文書には、

<!ELEMENT web-app (icon?, display-name?, description?, distributable?,
context-param*, filter*, filter-mapping*, listener*, servlet*,
servlet-mapping*, session-config?, mime-mapping*, welcome-file-list?,
error-page*, taglib*, resource-env-ref*, resource-ref*, security-constraint*,
login-config?, security-role*, env-entry*, ejb-ref*, ejb-local-ref*)>


のような定義がある。これは、配備記述子である XML 文書のルート要素が web-app であることと、それの子要素と多重度、子要素が親要素の中で出現する順番を定義している。ただ、Web コンテナがこの配備記述子を解釈するときに、URL で指定された DTD を読み込んでいるわけではないようだ。Web コンテナは最初から配備記述子のルールを知っているはずだからだ。このようにあらかじめ文書の定義について合意ができていれば、DTD は必要ではないはずだ。実際、XML では DTD は必須ではない。

HTML でも DTD を宣言することができる。たとえば、HTML 文書の先頭には

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">


を宣言することができる。これは、W3C が定義している HTML 4.01 の文書型定義(DTD)に準拠していることを宣言している。ブラウザによっては、この DOCTYPE 宣言を見て、HTML や CSS 解釈の挙動を変えたりする。宣言されていれば、HTML/CSS の仕様どおりの解釈をし、されていなければ過去の慣習的な「正しくない」解釈をする。Firefox や IE 6.0 は、この「DOCTYPE スイッチ」が機能する。