最近WebFontというものが流行ってきているらしい。通常のWebサイトでは各端末に入っているフォントをCSSで指定して使っているが、WebFontというのはフォントデータをサーバーから取得して使うしくみなのでユーザーの端末に入っていないフォントでも表示可能、また様々な種類のとても美しいフォントが用意されているといった点が大きな利点となっている。

なんだ素晴らしいじゃないかと手放しで喜びたくなるが「日本語」という壁が問題を少々複雑にしている。
英語のフォントであればキャラクタの種類が少ないのでWebでの配布に何の問題もないのだが日本語はそうはいかない。
キャラクタの種類が比べ物にならないのでフォントデータが巨大になりWebでのリアルタイムな配布に適さないのだ。
そこで日本語のWebFontを提供しているサービスではどこも「フォントのサブセット化」を行なっているようだ。
必要なキャラクターだけを組み込んだ「サブセット」のフォントデータを生成してデータサイズを小さくしようというのである。

今回ソフトバンク・テクノロジーが提供している フォントプラス を試す機会があったので感想を書いてみる。

まず、日本語のWebFontは現在のところ無料で提供されているサービスは存在しないと思われる。(英語であればGoogleWebFontなどがある。)理由はやはり上記の「フォントのサブセット化が必要」な点が大きいのではないかと思う。
フォントプラスではサブセット化の方式やPV数などで料金プランがわかれているようだ。ここではサブセット化の方式に注目してみてみると大きく2つの方式がある。

スマートライセンス

 javascriptでリアルタイムにフォントのサブセットを生成し、フォントプラスのクラウドサーバーからフォントデータを取得する形式。
 設置方法が非常に簡単(scriptタグの追加とフォント指定のみ)だが、WebFontが表示されるまでに1~2秒のタイムラグが発生するという問題がある。
 先にシステムフォントが表示され、1~2秒後にWebFontに切り替わるという見え方になる。
 これはリアルタイムにサブセットを生成しているという仕組み上しょうがない。

バリューライセンス

 事前に必要なフォントのサブセットを生成し、自社のWebサーバーに設置する形で使用する方式。
 フォント表示にタイムラグは発生しないが、CMSなど動的なページには向かない。
 (更新があるたびにサブセットを作り直す必要が出てくる。)

WebFontを使う箇所が固定文字(ex.ページのタイトルなど)であればバリューライセンスで問題ないのだが、動的なページとなるとやはりスマートライセンスでないと運用がしづらい。
しかしスマートライセンスでの見え方はそのままだとタイムラグがあるのでちょっとかっこわるい。
“スマート”に見せるにはエフェクトなどでタイムラグをごまかすような仕組みを検討しなければいけない。

バラ色の世界が広がるかに見えるWebFontであるが、こと日本語圏のWebでは今のところタイトルなどの一部の文字に部分的に使用するといった限定的な使い方が現実的なところだ。ただ、それだけでもこれまでいちいち画像で作っていた文字などをフォントで表示させられるというのはなかなか嬉しいものである。願わくば無料のサービスが登場して欲しいのだが。。

Comments WebFontの可能性と課題 はコメントを受け付けていません


ApacheでPATH_INFO(もしかしたらクエリーも)に%2F(/をURLエンコードしたもの)が入っていると404 Not Foundを返してしまい
意図したとおりに動作しないという現象でちょっと嵌った。

解決方法は非常に簡単で AllowEncodedSlashes パラメータを設定するだけだった。

AllowEncodedSlashes On

デフォルトではOffとなっている。

Comments [tips] PATH_INFOに%2Fが入ると404 Not Found になる件 はコメントを受け付けていません


概要

ServersMan@Disk は月額210円@10G(追加は105円@10G)という低価格に加えてLinuxサーバーにもマウントできるという面白い機能が用意されています。
ちょうどさくらのVPSの容量が少なくなってきたのでバックアップ領域としてこれを活用できないかと思い試してみました。
rsyncでコピーしたときに接続が切れてマウントできなくなるなど不安定な面もあるようですが、素晴らしいサービス設計だと思います。

インストールと設定

どうやらServersMan@DiskはWebDAVのようで、Linuxサーバーにはfuseを使ってマウントさせるようです。
まずfuseをインストールしておきます。

# yum install fuse fuse-devel

次にServersMan@DiskのLinuxクライアント(rpm)をダウンロードしてインストール。

# wget http://serversman.com/win/bin/smdisk-1.0-005.x86_64.centos.tar.gz

# rpm -ivh smdisk-1.0-005.x86_64.rpm
準備中...                ########################################### [100%]
   1:smdisk                 ########################################### [100%]

fstabにマウントの設定を追記します。

/usr/sbin/smdisk#https://webdav.disk.serversman.net/cldstg/webdav/ /mnt/smdisk fuse allow_other,umask=0000,username=xxxx@xxxx,password=xxxxxxxx,ope_src=xxxxxxx 0 0

mountコマンドでマウントさせてみます。

# mount /mnt/smdisk

# df -h
Filesystem          サイズ  使用  残り 使用% マウント位置
/dev/hda2              18G   13G  3.8G  78% /
/dev/hda1              99M   12M   82M  13% /boot
tmpfs                 250M     0  250M   0% /dev/shm
wdfs (https://webdav.disk.serversman.net/cldstg/webdav/)
                       10G     0   10G   0% /mnt/smdisk

素晴らしい!あとは普通のファイルシステムとして使えそうです。
ファイルを作成してみたところ、ユーザ、グループはroot,root、パーミッションは777で作成されました。

Comments ServersMan@DiskをさくらVPSにマウントしてみた はコメントを受け付けていません


概要

EC-CUBEはここ数年勢いを増していてかなり認知度があがってきています。2.11.4も登場してスマートフォン向けのデザインが強化されるなど、機能も充実の一途です。そんななかプログラマーを悩ませるのは、「コードが酷い」ということ。。もう少しきれいなコードだったらカスタマイズしやすいのになあ。。何度そういうため息を漏らしたことでしょう。
こういった状況を少しでも改善していきたいと、まずはDB操作のコードを楽にするためのプラグインを開発しました。
「開発した」といっても弊社で公開している Teeple2 というフレームワークのORマッパーである TeepleActiveRecord をEC-CUBE用に移植しただけなのでたいした工数はかからずにできました。
使い方はほぼ http://code.google.com/p/teeple2/wiki/DatabaseIntro こちらに書いてあるやり方と同じです。(こちらではPDOは使っていません。)
下のコードは同梱したテストケースからの抜粋ですがこんな感じでなにをやっているか一目瞭然のコードがかけます。


        $productList = Entity_DtbProductCategories::get()
            ->join('dtb_category')
            ->join('dtb_products')
            ->contains('dtb_category.category_name', 'なべ')
            ->contains('dtb_products.name', 'なべ')
            ->order('dtb_products.product_id')
            ->limit(10)
            ->offset(0)
            ->select();

        $this->assertEquals('おなべレシピ', $result[0]->dtb_products->name);

ダウンロード

こちら から。(無料でご自由にお使いいただけます。)

セットアップ方法

配布しているアーカイブは以下のようにEC-CUBEのディレクトリ構成と同じ形になっていますので、そのまま配置してください。
(実行に必要なのは data/plugin/activecube 以下のみです。)

data
  |- plugin
    |- activecube

test
  |- class
    |- activecube

次に data/require_classes.php の末尾に

require_once DATA_REALDIR . 'plugin/activecube/config.php';

と記述を追加してください。これだけで使えるようになります。

しくみ、注意点など

  • lowlevelでは EC-CUBEの SC_Query クラスを使用しています。トランザクションの制御などはこちらを使用して行なってください。本ライブラリはあくまでSC_Queryのラップであり、SQLを組み立てやすくしたり、結果セットの扱いをオブジェクト階層構造で扱えるようにしたりしています。
  • MySQL, 2.11版のみ用意しています。(私がMySQLしか使わないため。。) Postgresへの対応は少しの修正でできるのではないかと思います。
  • Entityクラスにjoinの設定があります。間違っていたり足りなかったりした場合はここを修正するとよいです。
  • Entityクラスに自由にドメインロジックを追加することができます。そのような使い方をすると便利かと思います。
  • ログはEC-CUBEのsite.logに出力されるようになっています。ログレベルを変更したい場合はActiveRecord.php の 48行目あたりを修正してください。
  • 本ライブラリはフリーで提供していますので、不具合等によるいかなる損害についても弊社では責任を負いません。自己責任でご利用をお願いします。

Comments EC-CUBEのDBを「流れるインターフェース」でらくらく操作できる「ActiveCube」を開発しました はコメントを受け付けていません


mysqlのサブクエリに問題があることはなんとなく見聞きしていたが今日はこれについて深く追求せざるを得ない機会があったので調べてみました。
自分なりに理解したので簡単にまとめてみるが、以下のブログの記事が素晴らしいので詳しくはそちらもあわせて読むと良いでしょう。

http://nippondanji.blogspot.com/2009/03/mysql_25.html

mysqlの実行計画を知るには

mysqlで実行計画を取得するには実行したいクエリーの前に EXPLAIN をつけるだけ。
実にシンプルだが、取得できるデータもシンプル極まりない(^_^;)

mysql> EXPLAIN SELECT COUNT(customer_id) FROM dtb_customer  WHERE  del_flg = 0  
AND customer_id IN (SELECT customer_id FROM dtb_order WHERE order_id IN 
(SELECT order_id FROM dtb_order_detail WHERE product_name LIKE '%とうもろこし%' ));
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
| id | select_type        | table            | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY            | dtb_customer     | ALL  | NULL          | NULL | NULL    | NULL | 1834 | Using where |
|  2 | DEPENDENT SUBQUERY | dtb_order        | ALL  | NULL          | NULL | NULL    | NULL | 2023 | Using where |
|  3 | DEPENDENT SUBQUERY | dtb_order_detail | ALL  | NULL          | NULL | NULL    | NULL | 2163 | Using where |
+----+--------------------+------------------+------+---------------+------+---------+------+------+-------------+
3 rows in set (0.02 sec)

実行計画の読み取り方は こちら に詳しく載っています。

IN句はEXISTS句におきかわる

さて、上にあげたクエリーは IN句に二重にサブクエリーが入っている、ツッコミどころ満載のSQLである。(実はEC-CUBEの中でこのクエリーが使われている。)
普通は1番内側のサブクエリーから実行されていって結果が返ってくるという動きを想像してしまうしそのほうが効率がいいのは明らかだ。
ところがmysqlでは外側のクエリーから実行し、得たレコードについて内側のサブクエリーを繰り返し実行するという処理になる。
つまりIN句なしで検索した結果が3000行ある場合、その各行についてサブクエリーの走査が実行するされるのでとんでもなく時間がかかってしまう。

何故このようになるかというとmysqlのオプティマイザがIN句をEXIST句に置き換えてしまうため、サブクエリーが相関サブクエリーとなり、結果上に述べた実行計画になってしまう。

DEPENDENT SUBQUERY に注意

このように実行計画で DEPENDENT SUBQUERY となっているものについては、 nxn の走査が走ってしまう可能性があるのでできるだけ排除したほうがいいだろう。
できる限りJOINを使うように心がけたい。

Comments [tips]なぜmysqlのサブクエリは遅いのか はコメントを受け付けていません