各ブラウザーのスーパーリロード

Operaがスーパーリロードに対応したという話を聞いて、気になって調べてみました。

Opera

Shift/Ctrl+リロード

http://www.forest.impress.co.jp/docs/news/20120328_521811.html
2012年3月27日リリースの11.62でスーパーリロードに対応なんだとか。そんな最近・・・

Firefox, Chrome

Shift+リロード

公式な説明見つけられなかったから、もしかしたらCtrl+リロードでもいけるかも?
Ctrl+リロードでも可能なようです。このエントリーのコメントを参照。

IE

Ctrl+リロード

IEはShiftじゃなくCtrlでちょっとはまった。IE9HTML5のサポートとかはかなりモダンブラウザ化してるから、Shiftで出来るようになってたりしないのかなー

余談

ページ遷移(リフレッシュ)

3つ目はちょっと良い名前が思いつかないのですが、リロードではなく、通常の画面遷移での読み込みのことです。アドレスバーにフォーカスしてenterするといった方法で実現できます。むしろこれこそが普通です。

君は3つのリロードを知っているか? - os0x.blog

ブラウザの挙動には、リロード・スーパーリロードの他に、ページ遷移(リフレッシュ)というのがあるという話。どのブラウザでも同じ挙動なのかは分からないけど、304かどうかも確認せずにブラウザキャッシュを使うって、リクエスト出さないみたい。

書いた日

2012-06-06
例によって下書きのまま放置してた

Macにwgetコマンドが無かったのでMacPortsで入れた

curlコマンドは使ってたけどwgetコマンドが無かったので入れました。どうもcurlだと、リンクを辿ってサイト全体をダウンロードするような機能が無いらしく、wgetの方を使いたくなりました。

それぞれの特徴をまとめますと、wgetはクローラとして、curlは連番ファイルのダウンローダとしての機能が盛り込まれています。

wgetとcurlの根本的な違い - ctrlshiftの日記

詳しくは引用元にあるけど、こんな特徴になっているらしい。

インストール

$ sudo port install wget

使い方というか備忘録

サイトを指定してミラー相当をダウンロードする
$ wget -mkKE http://example.com
-m --mirror -r -N -l inf --no-remove-listing

-mは、これらを指定した事になる。

-r --recursive 再帰的に取得する。ただし、robots.txtで拒否されている場合は、指定したページだけしか取得できない。
-k --convert-links ダウンロードしたhtmlファイルからのリンクや画像のパスをうまく表示できるように変換する
-K --backup-converted .origをつけて変換前のファイルを残す
-E --adjust-extension mod_rewriteされてたりクエリーストリングによってコンテンツが変わるサイトの場合、.htmlをつけて保存する。古いバージョンのwgetでは--html-extentionだったらしい。
-N --timestamping ローカルに同名のファイルがあって、ファイルサイズが同じ場合に、更新日時を比較してリモートのほうが新しければダウンロードする。
mirrorを知る前に使ってたオプション
$ wget -rpkK http://example.com
-p --page-requisites ページの表示に必要な画像やcssなどを合わせてダウンロードする。
robots.txtを無視する
$ wget -e robots=off

後述の.wgetrcで恒久的にoffにも出来る。

--restrict-file-names=windows
$ wget --restrict-file-names=windows example.com/index.php?foo

Windowsではファイル名に?を使えないのでindex.php?fooindex.php@fooにして保存する。?だけじゃなく\, |, /, :, ?, ", *, <, >とASCII制御文字も変換する。Windowsで動くwgetコマンドのデフォルトは--restrict-file-names=windowsになっているらしい。逆にUnix系で動くwgetコマンドは--restrict-file-names=unixがデフォルトらしいので、通常はあまり気にしなくてもよさそう。

.wgetrc
robots = off
user_agent = Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1
timeout = 120
passive_ftp = on

オプションで指定するほかにホームディレクトリに置くrcファイルでも指定できるものが結構あるみたい。

環境

Mac Mac OS X 10.5.8(Leopard
wget GNU Wget 1.13.4 built on darwin9.8.0.

書いた日

2012-02-13
例によって下書きのまま放置してた

MySQLのinnodbのインデックスについて調べてみた

innodbの主キー*1クラスターインデックス

クラスターインデックスでは、主キー(B-tree)のリーフページにデータが直接格納されています。
以下の図のようなイメージです。

株式会社スタイルズ

図は引用するとややこしいのでしてませんが、図を見たほうが分かりやすいです。

InnoDBの主キーは次の図のように「データが主キーのリーフノードに含まれる」という構造になっている。このような構造をクラスタインデックスという。

漢(オトコ)のコンピュータ道: 知って得するInnoDBセカンダリインデックス活用術!

理解しにくいとこなので、別のエントリーも引用。このエントリーにも分かりやすい図があります。

セカンダリーインデックスのリーフには主キーの値が入ってる

クラスタインデックスを用いる場合、データはすべて主キーに格納されているので、セカンダリインデックスは特殊な構造にならざるを得ない。セカンダリインデックスの値からデータを取得するにはどうすればいいのだろうか?ご存知の方も多いだろうが、セカンダリインデックスのリーフノードには主キーの値が格納されている。

漢(オトコ)のコンピュータ道: 知って得するInnoDBセカンダリインデックス活用術!

前述のエントリーだけど、セカンダリーインデックスの図も分かりやすい。

主キーを定義しない場合でも、結局主キーはある

もしテーブルに PRIMARY KEY を定義しなければ、MySQL は主キーとして NOT NULL カラムだけを持つ最初の UNIQUE インデックスを選択し、InnoDB がそれを集合インデックスとして利用します。もしテーブル内にそのようなインデックスがなければ、InnoDB は、行が InnoDB がそのようなテーブル内の行に割り当てた行 ID によってオーダされる集合インデックスを内部的に生成します。行 ID は、新しい行が挿入されると単調に増加する6バイトのフィールドです。従って、行 ID によってオーダされた行は物理的に挿入順になっています。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 14.2.13 InnoDB テーブルおよびインデックスの構造
主キーを定義
定義したものが主キーになる
NOT NULLかつUNIQUEインデックスが付いたカラムがある
それが主キー扱いになる
何も無い場合
内部的に主キーを生成する

自分のクラスターインデックスへの理解が間違ってなければ、innodbはそもそもデータをB+treeの中に置くので、主キーが無いとB+treeが構成できず、主キーが無いということはありえないはず。
あと、結局内部的に主キーが作られるので、主キーが要らない様なテーブルで、INSERTの負荷軽減の為に主キーを作らないのは、あまり意味がなさそう。

インデックスカーディナリティ

ユニークなレコードが多い程、カーディナリティが高くなる。カーディナリティが高いと、インデックスの効果が高くなる。要するに、違う値がなるべく多い、出来ればユニークなカラムほど、インデックスの効果が高い。

3つのカーディナリティ

データベースまわりでカーディナリティとか濃度という言葉がバラバラの意味で使われているので整理する。
以下の3種類の使われ方がある。

1. relationのカーディナリティ
リレーション中のタプルの数(不正確に言えばテーブル中のレコード数)をカーディナリティという場合。
これが原義。
Date「データベースシステム概論」P-90

一つの組(tuple)は表の一つの行に対応し、一つの属性(attribute)は一つの列に対応している。
組の数は濃度(cardinality)とよばれ、属性の数は次数(degree)とよばれる。

2. relationshipのカーディナリティ
エンティティ間の関係が1対1・1対多・多対多のどれか、ということをカーディナリティという場合。

3. キーのカーディナリティ
キーの値の数と、全レコード件数との比を、カーディナリティという場合。
日本語の「濃度」のイメージに近いのでわかりやすいような、そうでもないような。

http://www.oracle.co.jp/interactive/Techniques/VLDB/Dss/step0302.html
ビットマップ索引の効果を左右するのは「カーディナリティ」です。
「カーディナリティが低い」とは、索引キーの値が行数に比べて少ない種類の値しか取らないこと
を意味します。例えば「性別」は「男」「女」の2種類の値のいずれかになりますが、これは最も
カーディナリティの低いデータの例だといえます。
「行数に比較して少ない種類の値」というところがポイントです。値が2種類しかなくても、行数が
2行しかなければカーディナリティが低いとはいえません。また1万種類の値を取るデータでも、
行数が数億行あれば十分カーディナリティは低いといえます。

カーディナリティて何ですの - 極北データモデリング

RDBでテーブルの作り方が良くわからなくなってきたので、いったんまとめてみた - kanonjiの日記で、テーブルのhasOneやhasManyの関係の事をカーディナリティと呼ぶと思ってたので、インデックスカーディナリティは最初混乱しました。でも、どうやら合計で3種類のカーディナリティがあるらしい。カーディナリティって言葉に意味持たせすぎじゃ・・・

インデックスの情報を見る

SHOW INDEX FROM `テーブル名`;
|Table   |Non_unique|Key_name|Seq_in_index|Column_name|Collation|Cardinality|Sub_part|Packed|Null|Index_type|Comment|
+--------+----------+--------+------------+-----------+---------+-----------+--------+------+----+----------+-------+
|students|        0 |PRIMARY |          1 | id        | A       |     24964 |   NULL | NULL |    | BTREE    |       |
MySQLパフォーマンスチューニングのためのインデックスの基礎知識 - 久保清隆のブログ

こんな結果が得られる。各項目の説明は、引用元に表があります。

Covering Index

innodbで全行数をCOUNT(*)やCOUNT(id)で取得しようとすると、意外に重たい処理になるらしいです。主キーで数えれば、たいていの場合ただのintだしユニークだしインデックスもあるし、早そうな印象があります。どうやら、クラスターインデックスである事が原因で、主キーを構成するB-treeのリーフに、実データが入っている事から、全主キーを調べるという事はテーブルの全データを読み込むという事になるみたい*2です。

このような構造になっていることには利点と欠点があるが、大きな利点は主キーの値で検索をすると非常に高速だということだ。主キーのリーフノードにたどり着いたときには、既にデータのフェッチも完了している。データとインデックスが別々に格納されているタイプのストレージエンジンでは、インデックスからデータの位置を読み取って、その後データファイルからデータをフェッチする。このように二段階の操作が必要であると、キャッシュが効いていない場合には余分なディスクI/Oが生じてしまうだろう。だが、クラスタインデックスになっていると、インデックスを検索するだけでデータもフェッチできるのである。

漢(オトコ)のコンピュータ道: 知って得するInnoDBセカンダリインデックス活用術!

同じエントリーばかり引用してるけど、ここによると「主キーを検索するだけでデータもフェッチできる」とあります。だから「大きな利点は主キーの値で検索をすると非常に高速」ともあるんだと思う。このエントリーで明言してないけど、件数を調べるときに主キーを使っても、データもフェッチしてしまって、主キーを調べるだけというのが出来ないという事なのかな?

要はいかに I/O を減らすかが重要になってくるというわけです。例えばこのような SQL を考えてみます。

SELECT hoge, fuga FROM table_1 WHERE foo = 1;

普通に考えると [foo] にインデックスを張って、リーフで得られた値から他の列値 (hoge, fuga) を取得する、とやりたくなるところです。ただ、ここで [foo, hoge, fuga] という複合インデックスを張ることで、リーフだけで必要なデータが全て得られ、その後のランダムアクセスが無くなるため高速になります。このようなインデックスだけで完結するインデックスを Covering Index と言うそうです。

MySQLでインデックスを使って高速化するならCovering Indexが使えそう - (゚∀゚)o彡 sasata299's blog

ともあれ、Covering Indexを使うと高速になる可能性があるらしい。Covering Indexというのはインデックスだけで完結するインデックスだそう。

クラスタインデックスにおけるセカンダリインデックスは、悪いことばかりではない。そもそも検索がセカンダリインデックスだけで済むようにCovering Indexにすれば非常に高速だ。その辺の事情については、過去記事「InnoDBでCOUNT()を扱う際の注意事項あれこれ。」にも書いてあるので参照して頂きたい。

漢(オトコ)のコンピュータ道: 知って得するInnoDBセカンダリインデックス活用術!

Covering Indexについては、ちょっと複雑で引用するのにちょうど良い文量のエントリーが見当たらなかったけど、上記2つの引用元が分かりやすいです。

Covering Indexを使うにはセカンダリインデックスを使うので、COUNTが早くなっても更新処理が逆に遅くなるかも知れない。

SHOW ENGINE INNODB STATUS と InnoDBモニタ、innodbテーブルモニタ

InnoDBInnoDB 内部の状態についての情報をプリントする InnoDB モニタを含んでいます。ご自分の SQL クライアントにスタンダード InnoDB モニタのアウトプットをフェッチする為に、いつでも SHOW ENGINE INNODB STATUS SQL ステートメントを利用する事ができます。 この情報は性能調整をするうえで役立ちます。

http://dev.mysql.com/doc/refman/5.1/ja/innodb-monitor.html
SHOW ENGINE INNODB STATUS\G

innodbの内部情報を知るためのクエリーと、innodbモニタ、innodbテーブルモニタという機能もあります。

書いた日

2011-12-19
例によって下書きのまま放置してた、筈なんだけど、これを書いた記憶が無くって普通に読んでしまった。
他の下書きは、一応書いたって事くらいは覚えてるんだけどなぁ。
自分で読んでて「全主キーを調べるという事はテーブルの全データを読み込むという事」の根拠が無くて気になったので、ちょっと加筆しました。

*1:プライマリーキー

*2:どこでその情報知ったか分からなくなったので、ちょっと自信ないですが

debianのシェルがよく分からない

debianなサーバーでGNU screen使い出したら、プロンプトがsh-4.1$になっちゃいました。screen中もbashにしておきたいと思って調べてたら、なんかよく分からなくなりました。深く追いかける時間がないので、とりあえずのメモ。

初期状態*1

myuser@myhost:~$
$ printenv | grep SHELL
SHELL=/bin/sh
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 9 2011-04-23 20:02 /bin/sh -> /bin/bash

/bin/shの実体は/bin/bash

気になるとこ

$ vi .bashrc
echo 'load .bashrc' #1行目に追記
#ログインしなおすと'load .bashrc'が出る

SHELL=/bin/sh なのに.bashrcを読んでる。/bin/shの実体が/bin/bashだから?

$ /bin/sh
sh-4.1$

/bin/shの実体は/bin/bashのはずなのに、shっぽいプロンプト。

環境

debian wheezy/sid

書いた日

2011-12-10
例によって下書きのまま放置してた

*1:ただ、サーバーがセットアップしてからしばらく色々と使ってます。

Google AppsのGmailでニックネーム(エイリアス)を設定してフィルターで判別する

Google Appsでは、ニックネームという名称のエイリアス機能があります。foo@example.comというメールアドレスを持つGoogle Appsのユーザーfooに、管理画面からニックネームを付ける事が出来ます。ニックネームの項目には気がついていたんですが、これってGmailでTo:を入力する際の補完用のものかと思ってたら、なんかエイリアスでした。bar@example.comというメールアドレスをニックネームに設定すると、foo@example.comのアカウントで受信出来るようになります。

注: Google Apps 管理者用コントロール パネルでは、メール エイリアスがニックネームと呼ばれます。

Add or remove an email alias - G Suite Admin Help

なら、エイリアスって書いておいてほしい・・・

フィルタ設定

deliveredto:(bar@example.com)

キーワードにこれを設定すると、エイリアス宛のメールが抽出出来ると思います。

送信

Send emails from a different address or alias - Gmail Help

ニックネームは受信だけなので、送信用に設定する必要はあります。Senderヘッダーで、元のメールアドレスは通知されるので、それが困る場合はニックネーム機能じゃダメです。

書いた日

2011-11-30
例によって下書きのまま放置してた

Googleマップのマイプレイスの名前を変える方法

Android端末を持ち歩くようになってから、知らない場所に行く場合には必ずGoogleマップアプリを使い、行き先の住所で検索して地図を見ながら向かいます。行き先が多い場合には、事前に調べてマイプレイスに登録します。マイプレイスはGoogleマップの機能で、検索した住所や座標など、マーカーの示す場所用のいわゆるお気に入り登録です。Android端末とPCとで同じGoogleアカウントなら、マイプレイスは同期されるので、PCで調べてマイプレイス登録しておくという方法もありです。

マイプレイスの名前を変える方法と理由

理由


まず理由からですが、Googleマップで住所で検索して出てきたマーカーをマイプレイスにしたら、そのまま住所で登録されます。例えば東京都庁をマイプレイスにしたくて「東京都新宿区西新宿2丁目8−1」で検索したら、Googleマップアプリのマイプレイス一覧でも「東京都新宿区西新宿2丁目8−1」と表示されます。こんなの後で見て東京都庁だって分かりません。この住所で登録したマイプレイスを、どうにかして名前変更したいんですが、Googleマップアプリでも、PCのGoogleマップでも、名前変更出来そうなUIが見当たらなかったです。
なお、目的地が有名なら上記画像の通り、「東京都庁」で検索して正しい位置にマーカーが出るので、これをマイプレイスにすればやりたい事ができます。でも、店名とか会社名とかだと、大抵の場合正しい位置にマーカーは出ません。

方法

Googleブックマークを使えば、マイプレイスの名前を変更出来ます。マイプレイスって実はGoogleブックマークの一つのブックマーク扱いになります。なので、マイプレイスを登録してからGoogleブックマークを開くと、そこには登録した住所と、その場所にマーカーがあるGoogleマップへのリンクがブックマークされてます。そして、ブックマークの編集として、サイト名を「東京都庁 東京都新宿区西新宿2丁目8−1」などと変える事で、マイプレイスの名前が変わります。

捕捉

Androidのバージョンとかも関係するかもしれませんが、自分の場合、Googleマップアプリのマイプレイス一覧に出る名前が変わりません。同期しなおしてもいつまでたっても「東京都新宿区西新宿2丁目8−1」と表示されます。そのマイプレイスをタップして詳細を開いたり、地図上のマーカーから出るバルーンには、変更済みの名前が載るんですが。
そこで、一度マイプレイスの詳細を開いて、スターをタップしてマイプレイスから外し、そのままもう一度タップして再度マイプレイスにします。そうすると、マイプレイスの一覧で変更済みの名前になります。多分バグなんじゃないかとは思いますが、一応回避は出来ました。

環境

Android 2.3.3
Googleマップアプリ 5.11.0

書いた日

2011-11-29
例によって下書きのまま放置してた

MacPortsで入れる代わりに自前でビルドしたライブラリを使ってswftoolsをビルドしてみた

MacPortsでswftools@0.9.2を入れようとしたら失敗した - kanonjiの日記でインストール出来なかったswftoolsを、なんとかビルドしてみました。

状況

$ port installed giflib
The following ports are currently installed:
  giflib @4.2.0_2+x11 (active)

MacPortsではgiflibは4.2.0になっていて、これだとswftoolのビルドは出来ません。MacPortsはパッケージのダウングレードがとても面倒なので、古いgiflibを自前でビルドして、それを使ってswftoolも自前ビルドする方法を探ってやってみました。

なお、調べながらやってみたということで、これが正しい・最善の方法かどうかはちょっと自信がありません。

$ pwd
/Users/myuser/Downloads/swftools-0.9.2
$ ./configure --help
[snip]
Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  LIBS        libraries to pass to the linker, e.g. -l<library>
  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>
  CXX         C++ compiler command
  CXXFLAGS    C++ compiler flags
  CPP         C preprocessor
  CXXCPP      C++ preprocessor

Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.

configureのヘルプを見たら、最後のほうにLDFLAGSLIBSの2つの環境変数が書いてありました。どちらもライブラリのパスを指定するものみたいで、LDFLAGSは標準的な場所にないライブラリを指定する的な事が書いてあります。この辺りを調べたら、どうやらいけそうなのでLDFLAGSを使ってビルドしました。

手順

$ cd /Users/myuser/Downloads/giflib-4.1.6
$ ./configure --prefix=/Users/myuser/local/
$ make
$ make install
$ cd /Users/myuser/Downloads/swftools-0.9.2
$ LDFLAGS=-L/Users/myuser/local/lib/ ./configure --prefix=/Users/myuser/local/
$ make
$ make install

動作すると思われる4.1.6のgiflibをビルドし、swftoolsconfigureのコマンド変数として、LDFLAGS=-L/Users/myuser/local/lib/を設定します。
/Users/myuser/localには/usr/localと同じようにbinやlibやincludeなどが作られて、インストールされます。/usr/local/libは、ライブラリのパスも通ってるので、古いgiflibを入れると、今後giflib 4.2.0で問題ないものまで4.1.6とくっついちゃうかもと思って、一時的な場所にインストールしました。

$ cd /Users/myuser/local/bin
$ ./swf[tab][tab]
swfbbox     swfc        swfcombine  swfdump     swfextract  swfrender   swfstrings

無事、giflib 4.1.6を使ってswftoolsのビルドが出来たみたいです。

補足

LDFLAGSにセットする値

./configure --helpを見てください。
LDFLAGS linker flags, e.g. -L if you have libraries in a
nonstandard directory
LIBS linker flags, e.g. -l.{a,so} if you have nonstandard
libraries to link
とあります。

これらの変数は最終的にMakefile
$(CC) $(LD_FLAGS) -o taget $(LIBS)
のように使われます。
ですからgccに与えるオプションをそのままわたせばいいと思います。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=3865&forum=10

パスだけじゃなく-Lオプションも含めて書く必要がある。

LIBS

LIBS='-lsocket -lnsl'

http://page.freett.com/ux4800/memo/mh-6.8.4-JP-3.03.inst48.txt

LIBSは今回使ってないので、よく分からずじまいだけど、検索していた感じ、上記のようにパスよりもライブラリ名?を指定している様子。前述の引用にある説明からすると、socket.asocket.sonsl.ansl.soをライブラリに指定した事になるのかな?パスじゃなく名前だけってとこから考えると、依存するライブラリの追加って事で、探す場所はLDFLAGSと元々システムが把握してるライブラリのパスって事になるんだろうか。

otool -L

リンクしてる共有ライブラリを確認するコマンドotool -Lの結果を追記しておきます。Linuxlddは無く、その代わりとなるコマンドです。

$ otool -L local/bin/swfextract
local/bin/swfextract:
	/opt/local/lib/libmp3lame.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	/Users/myuser/local//lib/libgif.4.dylib (compatibility version 6.0.0, current version 6.6.0)
	/opt/local/lib/libjpeg.8.dylib (compatibility version 13.0.0, current version 13.0.0)
	/opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.7)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.7)
	/opt/local/lib/libfreetype.6.dylib (compatibility version 16.0.0, current version 16.0.0)
	/opt/local/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.6)
	/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

環境

Mac Mac OS X 10.5.8(Leopard
システムにあるgiflib 4.2.0
ビルドに使ったgiflib 4.1.6
ビルドしたswftools 0.9.2