Home > 未分類
未分類
temporary table を試してみる(前篇:SQLの速度アップ)
- 2009年8 月18日(火)
- 未分類
こんにちは、tatsumi です。
やっと関西地方も遅い梅雨明けを迎えました。
暑さが厳しくなっておりますが、みなさまはいかがお過ごしでしょうか。
私はといえば、毎年恒例の富士登山へ行ってまいりました。
天気予報によると「曇り一時雨か雷雨」という状態でしたが、
5合目まで行ったら綺麗な空!
「なんだかー、行けそうな気がするー!!」ということで決行したものの、
頂上へ辿り着く直前に雨が降ってきてご来光が全く見れず。
山頂は暴風雨で身の危険を感じ、さっさと下山してきました。
「自然は壮大で美しい。だけれども、厳しい」
そんなことを改めて認識した夏でした。
ところで、今日は MySQL のTEMPORARY TABLEについて書いてみようと思います。
TEMPORARY TABLE とはずばり一時テーブルのことで、マニュアルによると
テーブルを作成する時、TEMPORARY キーワードを利用する事ができます。TEMPORARY テーブルは現在の接続でのみ現れ、接続が終了すると自動的にドロップされます。これは、2つの異なる接続同士、または、既存の同名の非TEMPORARY テーブルとお互いに対立する事無く、同じテンポラリ テーブル名を利用する事ができるという意味になります。(テンポラリ テーブルがドロップされるまで、既存テーブルは隠されています。)テンポラリ テーブルを作成する為には CREATE TEMPORARY TABLES 特権を持つ必要があります。
というもの。
作り方は簡単で、普通の CREATE TABLE 文に TEMPORARY キーワードをつけて
CREATE TEPMPORARY TABLE とするだけです。
「で?」と思われる方もいらっしゃいますが、
この TEMPORARY TABLE を上手く使うと色々なメリットがあります。
そのメリットとはざっくり2つ。
「SQLの速度アップ」と「ロックの回避」です。
今回は、SQLの速度アップについてご説明します。
複雑な集計などを行う際に、サブクエリを使うことがあると思います。
例えば、
select user.user_id, sammary_1.value, sammary_2.value, sammary_3.value from user -- 1列目に出したい集計値 left join ( [サブクエリ] ) as summary_1 on user.user_id = summary_1.user_id -- 2列目に出したい集計値 left join ( [サブクエリ] ) as summary_2 on user.user_id = summary_2.user_id -- 3列目に出したい集計値 left join ( [サブクエリ] ) as summary_3 on user.user_id = summary_3.user_id
といったような場合です。
このとき、全体のデータ量が少なければ大した問題にならないのですが、
ちょっとデータ量が多くなると急に遅くなります。
理由はEXPLAIN を実行すると一目瞭然ですが、
サブクエリの結果を結合する際に「条件のFULLスキャン」が発生するためです。
ここで TEMPORARY TABLE を使用します。
-- 1列目に出したい集計値 create temporary table summary_1( PRIMARY KEY(user_id) ) [サブクエリ]; -- 2列目に出したい集計値 create temporary table summary_2( PRIMARY KEY(user_id) ) [サブクエリ]; -- 3列目に出したい集計値 create temporary table summary_3( PRIMARY KEY(user_id) ) [サブクエリ]; -- 集計結果をまとめて表示する select user.user_id, sammary_1.value, sammary_2.value, sammary_3.value from user left join summary_1 on user.user_id = summary_1.user_id left join summary_2 on user.user_id = summary_2.user_id left join summary_3 on user.user_id = summary_3.user_id
実は TEMPORARY TABLE にも PRIMARY KEY などのインデックスを設定することが可能なので
上記のようにすれば、結合時にインデックスが使用されることになり
データ量が増えても比較的高速に検索することが可能になります。
もちろん、新規にテーブルを作成するコストやインデックスを作成するコストが新たに発生するので
上記のように書けば速くなるとは一概には言えません。
しかし、どうにも速度が出ないと悩んでいるのであれば試してみる価値があると思われます。
いかがだったでしょうか。
サブクエリを TEMPORARY TABLE に抜き出して
PRIMARY KEY を設定し、結合にインデックスを使用できるようにする。
あまり使用する頻度は高くないと思いますが、
こんなことができるというご紹介でした。
次回は TEMPORARY TABLE を使用して「ロックを回避する」ことについて書きます。
TCPDFを使ってみる
- 2009年7 月13日(月)
- 未分類
UTF-8が使えるPHPのPDFライブラリを探していた時に
TCPDFというのがあると知り、色々と調べていたところ
「フォント埋め込みされることが原因で、ファイルサイズが大きくなってしまう」
というコメントがたくさん見つかりました。
そこで、マニュアルを読んだところ
フォント埋め込みをせずにPDF出力する方法があると分かったので
ちょこっとご紹介。
1.ダウンロード
TCPDFの本家サイトから最新のソースをダウンロードする
http://www.tecnick.com/public/code/cp_dpage.php?aiocp_dp=tcpdf
2.フォント設定
デフォルトでは日本語が使えないようなので、今回はMS明朝を使えるようにしてみます。
①ms-mincho.ufmファイルを生成する
C:\WINDOWS\Fonts にある MSMINCHO.TTF を ms-mincho.ttf にリネームして、
TCPDFのルートディレクトリ配下にある [TCPDF_ROOT]\fonts\utils に配置して、下記コマンドを実行します。
[コマンドプロンプト]
> cd [TCPDF_ROOT]\fonts\utils
>ttf2ufm.exe -a -F ms-mincho.ttf
②ms-mincho.phpファイルを生成する
ms-mincho.ttf ファイルと ms-mincho.ufm ファイルから ms-mincho.php ファイルを生成します。
[コマンドプロンプト]
>php -q makefont.php ms-mincho.ttf ms-mincho.ufm 0
※ここでmakefont.php の第3引数に 0 をセットすると、
PDFファイルにフォント埋め込みを行わなくなります。
何も指定しない場合は、フォント埋め込みが行われファイルサイズは大きくなります。
③ms-mincho.phpファイルを編集する
先ほど作成した ms-mincho.php ファイルを編集します。
[テキストエディタ]
//フォントタイプを変更する。
$type=’cidfont0′;
//デフォルトのフォント幅を設定する。
$dw=1000;
$name=’MS-Mincho’;
$desc=array(’Ascent’=>859,’Descent’=>-141,’CapHeight’=>27,
‘Flags’=>32,’FontBBox’=>’[-82 -137 996 859]‘,
‘ItalicAngle’=>0,’StemV’=>70,’MissingWidth’=>600);
$up=-94;
$ut=47;
$cw=array(【長すぎるので省略】);
$diff=”;
//不要なので削除する
//$enc=”;
//$ctg=”;
//$file=”;
//下記を追加する
$enc=’UniJIS-UTF16-H’; //UniJIS-UTF16-V にしたら縦書きフォントになる
$cidinfo=array(’Registry’=>’Adobe’, ‘Ordering’=>’Japan1′,’Supplement’=>5);
include(dirname(__FILE__).’/uni2cid_aj16.php’);
④ms-mincho.phpファイルを移動する
[コマンドプロンプト]
>move ms-mincho.php ..\
⑤ms-mincho.phpファイルをコピーする
移動したファイルをボールド・イタリック・ボールドイタリック用にコピーして別名で保存する。
[コマンドプロンプト]
> cd [TCPDF_ROOT]\fonts
>copy ms-mincho.php ms-minchob.php
> copy ms-mincho.php ms-minchoi.php
> copy ms-mincho.php ms-minchobi.php
3.使ってみる
[テキストエディタ]
//TCPDFクラスを読み込む
require_once(‘TCPDF.php’);
//TCPDFインスタンス化
$pdf = new TCPDF(’L');
//ページ追加
$pdf->AddPage();
//フォント指定&描画
$pdf->SetFont(’ms-mincho’, ”, 16);
$pdf->SetXY(15, 20);
$pdf->Cell(100, 10, ‘TCPDF設定完了!’, 0, 0);
//出力
$pdf->Output();
これでファイルサイズがぐぐんと小さくなりましたね。
TCPDFはかなりのペースでリリースが行われているので
どんどん良いものになっていっています。要チェックですね。
javascriptのprototypeプロパティでハマった
- 2009年3 月31日(火)
- 未分類
どうも。shimazakiです。
javascriptでprototypeプロパティについてアレコレしていたら自分が大きく誤解をしていたことを理解しましたので、ついでに紹介したいと思います
以下の結果がどうなるか、って分かりますか?
Hoge.prototype = {
aList:["123"]
,xList:["456"]
};
foo = new Hoge();
foo.aList = ["789"];
foo.xList.push("789");
alert(foo.aList);//789
alert(foo.xList);//456,789
bar = new Hoge();
alert(bar.aList);//???
alert(bar.xList);//???
正解はbar.aListは「123」 bar.bListは「456,789」と表示されます。
何を勘違いしていたか?
なでしこのススメ
- 2009年2 月26日(木)
- 未分類
shimazakiです。
先日社内で勉強会を勉強会を行ったのですが、DOM入門ともう一つ、「なでしこのススメ」というタイトルで発表を行い、「日本語プログラミング言語・なでしこ」の社内普及に乗り出してみました。
日常の単純作業やめんどくさい単調作業など、せっかくだから、プログラム作っちゃいませんか、なでしこで。
Unionを使わない複数集計
- 2009年2 月24日(火)
- 未分類
shimazakiです。
今日はSQLの話です。
SQLってプログラムと違い、上から順に処理されるわけではなく、まとめて処理されるのでなかなか理解できません。
SQLってこんなことも出来たのか!と感動した時の話をしたいと思います。
例えばこんなテーブルがあったとして(試験の結果テーブルだと思っていただければ)
- sampleTbl
- 100点の人数と、90〜99点の人数と、80〜89点の人数と70〜79点一覧を抽出したい場合
| ID | point |
|---|---|
| A | 100 |
| B | 90 |
| C | 88 |
| D | 70 |
| E | 95 |
| F | 80 |
select 'p100' as pnt,count(*) as cntpoint from sampleTbl where point = 100
union
select 'p90' as pnt,count(*) as cntpoint from sampleTbl where point between 90 and 99
union
select 'p80' as pnt,count(*) as cntpoint from sampleTbl where point between 80 and 89
union
select 'p70' as pnt,count(*) as cntpoint from sampleTbl where point between 70 and 79;
pnt cntpoint p100 1 p90 3 p80 1 p70 1
というSQLを、
select
sum( if( point=100, 1,0)) as p100,
sum( if( point between 90 and 99 , 1,0 ) ) as p90,
sum( if( point between 80 and 89 , 1,0 ) ) as p80,
sum( if( point between 70 and 79 , 1,0 ) ) as p70
from sampleTbl;
p100 p90 p80 p70 1 3 1 0
と言うSQLに変更します。
条件に一致する行を1とし、その個数をカウントすることで、結果を一行で取得することができます。
これが、単一の試験結果であればそれほど利点はないのですが、例えば、今回のテスト結果と前回のテスト結果を表示する画面、というものがあった場合、先述のunion方式では結果データの構成が複雑になってしまいますが、後述の方法であれば、今回の結果行と前回の結果行という取得が可能なので、結果データの構成が分かりやすくなります。
SQLの理解がまだまだ足りないと思う今日この頃でした。
Home > 未分類