MySQLのMERGEテーブル

Oracleで言うパーティショニング、SQL Serverで言うパーティション分割のような
機能をMySQLで使いたくて調べてみた。


厳密に同じものは存在しないが、MERGEテーブルがまだ近い。
しかし、

  • MyISAMでしか使えない。
  • レンジ毎に格納する領域を指定できない。

といったところに問題を感じる。


とりあえずパフォーマンスを試してみようと思い、ダミーデータを作った。


CREATE TABLE t1 (
id INT NOT NULL DEFAULT 0,
date DATE NOT NULL,
code INT NOT NULL DEFAULT 0,
quantity DECIMAL(7,2) NOT NULL DEFAULT 0,
price DECIMAL(7,2) NOT NULL DEFAULT 0,
amount DECIMAL(9,0) NOT NULL DEFAULT 0,
PRIMARY KEY(id),
INDEX DATE(date)
) TYPE=MyISAM;

t1〜t5に20万ずつ挿入。

CREATE TABLE total (
id INT NOT NULL DEFAULT 0,
date DATE NOT NULL,
code INT NOT NULL DEFAULT 0,
quantity DECIMAL(7,2) NOT NULL DEFAULT 0,
price DECIMAL(7,2) NOT NULL DEFAULT 0,
amount DECIMAL(9,0) NOT NULL DEFAULT 0,
PRIMARY KEY(id),
INDEX DATE(date)
) TYPE=MERGE UNION=(t1, t2, t3, t4, t5)

よく使うSELECT文を試していたら、


SELECT * FROM total WHERE id < 10000 ORDER BY id DESC LIMIT 1
が遅い。
MySQLのバージョンが4.0.25で平均して1.8602秒くらいかかる。
試しに5.0.10で試したら平均して0.1093秒くらい。
4.1系は試していないけど、バージョンによってかなり違う。

タブの試験実装

ファイルリストをタブかMDIに乗せようかと思っていたけど、
整理しづらく使いにくい。
タブブラウザなどで使われているグループタブは
ファイラとしては一覧性が低い。
分割タブとして2つのタブコントロールを使う手もあるけど、
2つと固定的なのもいまいちか。


何か良い方法はないかと考えていたところ、
ecliseで使われているようなネスト可能な分割タブを思い出した。
ただ実装方法が良く分からなかったので試作してみた。


短いサンプルが見つからなかったので、
とりあえず手を動かしていたら、バグバグだけそこそこ動くものができた。
本実装の目処はつけることができた。


...しかしeclipseで使われているネスト可能な分割タブって
正式にはなんて呼ぶんだろ?

DnD

エクスプローラDnDの挙動が違っていたので修正した。

  • 同Window内のDnDの制限
  • 右ドラッグ時のポップアップメニューの項目
  • スクロール速度

気づいている範囲は似せることができたと思う。
試行錯誤が多くて苦労した。


そういやまだIDropTargetHelperを使っていないや...。

マルチスレッド

アイコンの取得、サムネイルの取得にもワーカースレッドを使うようにした。
UIが固まることが無くなって満足。
まだスレッド関係でまずいところがあるけど、それはおいおい修正するつもり。

アイコン

アイコンの取得に時間がかかるかどうか判定する方法を見つけた。
IShellIcon::GetIconOfでIExtractIcon::GetIconLocationの
パラメーターを使うというもの。
MSDNには記載されていないので邪道かもしれない。



int icon;
IShellIcon* si;
hr = sf->QueryInterface(IID_IShellIcon, (void**)&si);
if (hr == S_OK) {
// ここでGIL_ASYNCを使うのがミソ
switch (si->GetIconOf(fi->_il, GIL_ASYNC, &icon)) {
case NOERROR:
// アイコンを速く取得できた場合
break;
case E_PENDING:
// アイコンの取得が遅い場合
// この場合imageは未定義のindexが代入されている
break;
case S_FALSE:
// 取得できない場合がある
break;
}
} else {
// IShellIcon*が取得できない場合がある。
}