昨日、家の近所の神社でお祭りがあった。
天狗が出てくると言うので、朝の10時頃に見に行ったら、すでに子供神輿は終了していて境内では子供たちが騒ぎ、数えられるぐらいの老人たちが神事を見守っていた。神社の本殿では神事が執り行われていて、スーツを着た人や法被を着た人たちが、神主からお祓いを受けたり、巫女さんが舞ったり、お神酒を受けたりしていた。
「あの中の誰が天狗に変身するんだろう?」
「神主が祭壇へ登ってお神酒をとっているついでに天狗に変身するんじゃないか?」
「あのスーツを着た足元おぼつかない最長老が、天狗に豹変するに違いない」
などと言いつつ見守る。
待ちくたびれて座り込んでいる孫を連れたおじいちゃんが「天狗出てくるで」と言っているので、天狗がでてくる事自体は間違いないようだ。
そうこうしているうちに神事は無事終了し、神主さんが表に出てきて「どうぞお入りください」などと言う。
見物人もいつしか数十人になっていて、ぞろぞろと本殿の中へ。
要領が分からずまごついていると、お婆さんから「早くから来られてたんだから、どうぞお先に」と勧められ、一同と一緒に本殿内へ入り着席。
後ろの方では何やら「二人分の席が足りない」などの声が聞こえる。
やがてお神楽が始まり、巫女さんが剣と鉾で舞い始め、神楽鈴(手に持つ鈴がたくさんついた物)でお祓いも受ける。すると三宝に載った赤いキーホルダーが出てきて、参加者に配られ始めた。
しかしよく見ると、周りの人は小さなピンク色の小さな紙切れを持っていて、それと引き換えに授かっているようだ。
我々は飛び入りでそんなものは持っていない。
「なに!部外者が居るだと?」
「者ども出会え出会え!」
「氏子にも成らずして天狗様のお力を甘受するなど!」
などと言う事はなかったが、ちょうど受け取った者から解散のような状態になっていたので、そそくさと退散。
同じ町内に住んでいるのだけど、昔から付き合いのあるところにしかお知らせは回っていないのか、町内会に入っているところだけなのか、我々の住むマンションにまでは氏子募集のお知らせは来てなかったのだった。あの紙の相場はいくらぐらいするのだろう。
きっと後ろで座れなかった人たちの席を取ってしまったんだ。申し訳ないことをした。
教訓、神事への飛び入り参加は注意しよう。
2012/10/07
2012/08/19
カブのエンジンオイルを交換
メーター11008km。
4500kmぐらい走ってしまった。お店の人はオイルの交換は5000kmぐらいでいいって言ってた気がするんだけど、ネットで検索するとマニュアルには3000kmって書いてあるらしい。マニアっぽい人は1000kmで交換してるとか。
5000kmも交換しなかったら3年ぐらいで駄目になるとマニアっぽい人は書いていた。お店の人はまた買わせるためにそう言ったのかな?
ペットボトルを半分に切って、そこに受けるようにした。
「ドレンボルトを閉めすぎるな、最初に締まっていた感覚で閉めろ」とネットには書いてあったが、結構強く締まっていた。
ドレンボルトはエンジンの真下、17mm。斜めに付いている14mmを開けちゃうと、なんかバネとか出てくるらしい。
オイルが出なくなっても、キックスタートのペダルを踏めば出てくる。
もう出ないかなってところでドレンボルトを締めて、上からオイルを注ぐ。キャップを何度か閉めて注油量を確認。
それからチェーンの調整も行った。
チェーンカバーを外してたるみを確認。チェーンカバーは外さなくても、黒いカバーを外せばたるみは確認できる。
今回はもうたるんでいるのが音で分かったので、最初からカバーを外してしまう。
後輪位置を決めるのは自転車と同じ。左右のねじを調整して、チェーンがまっすぐになるように。
メモリが付いているけど左右でずれているので信用できない。1cmぐらいのたるみを残しておく。
オイル交換後は若干エンジンが掛かりにくかったが、何度かキックしたりセルモーターを回すとエンジンが掛かる。
アイドリング音もしずかになって、回転数も下がった感じ。
チェーンのたるみがなくなった分、ミッションを切り替えたときの前後の振動がなくなった。
延びすぎたらチェーン交換という認識でいいのかな。
後輪のチェーンが噛む部分がサビだらけだったけど、油が足りないのだろうか?
チェーン側の油は足りなさそうだったので、機械油を指した。
4500kmぐらい走ってしまった。お店の人はオイルの交換は5000kmぐらいでいいって言ってた気がするんだけど、ネットで検索するとマニュアルには3000kmって書いてあるらしい。マニアっぽい人は1000kmで交換してるとか。
5000kmも交換しなかったら3年ぐらいで駄目になるとマニアっぽい人は書いていた。お店の人はまた買わせるためにそう言ったのかな?
ペットボトルを半分に切って、そこに受けるようにした。
「ドレンボルトを閉めすぎるな、最初に締まっていた感覚で閉めろ」とネットには書いてあったが、結構強く締まっていた。
ドレンボルトはエンジンの真下、17mm。斜めに付いている14mmを開けちゃうと、なんかバネとか出てくるらしい。
オイルが出なくなっても、キックスタートのペダルを踏めば出てくる。
もう出ないかなってところでドレンボルトを締めて、上からオイルを注ぐ。キャップを何度か閉めて注油量を確認。
それからチェーンの調整も行った。
チェーンカバーを外してたるみを確認。チェーンカバーは外さなくても、黒いカバーを外せばたるみは確認できる。
今回はもうたるんでいるのが音で分かったので、最初からカバーを外してしまう。
後輪位置を決めるのは自転車と同じ。左右のねじを調整して、チェーンがまっすぐになるように。
メモリが付いているけど左右でずれているので信用できない。1cmぐらいのたるみを残しておく。
オイル交換後は若干エンジンが掛かりにくかったが、何度かキックしたりセルモーターを回すとエンジンが掛かる。
アイドリング音もしずかになって、回転数も下がった感じ。
チェーンのたるみがなくなった分、ミッションを切り替えたときの前後の振動がなくなった。
延びすぎたらチェーン交換という認識でいいのかな。
後輪のチェーンが噛む部分がサビだらけだったけど、油が足りないのだろうか?
チェーン側の油は足りなさそうだったので、機械油を指した。
2012/06/21
Windows7をバックアップイメージ経由で移動
パラレルATA接続のハードディスクでWindows7を使っていたのだけど、いい加減速度が遅いのでシリアルATAのハードディスクに移動することにしました。
パーティションをコピーするツールを使ってコピーしてみたのですが、ブートの情報までコピーされないのか起動してくれない。
そこで以前、Windows7のバックアップを経由して別ディスクに移動したことがあるので、この方法で行ったところはまりました。
結論から言うと「バックアップの取得時と復元時に余計なドライブを繋ぐな」 ということ。
以下が流れ。
コントロールパネルのバックアップから、「システムイメージの作成」で余っているハードディスクにバックアップをとります。
そして新しいディスクを繋ぎ、回復ディスクから、修復モードを立ち上げます。
(どうでもいいけど、回復ディスクをUSBメモリに出来ませんかね、マイクロソフトさん)
Windowsのような画面が起動し、IMEの種類を選択したところで、
はて、バージョンが違うってどういうこと?回復ディスクは以前作ったやつで、サービスパックが当たっていないから?
ということで、再度回復ディスクを作り直してチャレンジ。
しかし改善しない。
ハードディスクを繋ぎ直したりしているうちに気がついたのが、データ用ドライブに昔システムが入っていて、そのバージョンを認識してエラーが出ている様子。
回復ディスクで起動するときは、システムが入る予定のドライブだけを繋ぐことで突破出来た。
(なんでこれから回復するっていうときに、別のドライブの残りかすを見てエラーにするんでしょうか、マイクロソフトさん。バックアップイメージと回復ディスクのバージョンを比較するべきでしょう)
なんとか復元対象のバックアップイメージを選択し、回復がスタートしたところですぐにエラー。
復元開始直前に、復元対象から除外するディスクを選択出来る画面があったのですが、そこでは復元先ディスクが表示されていました。
もちろん除外対象にもなっていません。
ネットで検索してみたところ、どうやらバックアップ時に接続されていたディスクの容量からサイズが減るとこのエラーが出るらしい。
このとき、バックアップ時にデータドライブが繋がっており、バックアップ対象にはしていないのに回復時に存在しないため、容量が足りないと認識されていたようだ。
(何この仕様?)
結局、バックアップを取るときにはシステムドライブと、バックアップイメージ保存ドライブだけを繋いでバックアップ。復元時は、復元先ドライブと、バックアップイメージ保存ドライブ、CD/DVDドライブだけを繋いで起動するとよいようです。
もうちょっと分かりやすい仕様になりませんかね。せめてメッセージだけでも。マイクロソフトさん。
パーティションをコピーするツールを使ってコピーしてみたのですが、ブートの情報までコピーされないのか起動してくれない。
そこで以前、Windows7のバックアップを経由して別ディスクに移動したことがあるので、この方法で行ったところはまりました。
結論から言うと「バックアップの取得時と復元時に余計なドライブを繋ぐな」 ということ。
以下が流れ。
コントロールパネルのバックアップから、「システムイメージの作成」で余っているハードディスクにバックアップをとります。
そして新しいディスクを繋ぎ、回復ディスクから、修復モードを立ち上げます。
(どうでもいいけど、回復ディスクをUSBメモリに出来ませんかね、マイクロソフトさん)
Windowsのような画面が起動し、IMEの種類を選択したところで、
このバージョンのシステム回復オプションは、修復しようとするWindowsのバージョンと互換性がありません。このバージョンのWindowsと互換性のある回復ディスクを使用してくださいと言われて先に進めなくなってしまう。
はて、バージョンが違うってどういうこと?回復ディスクは以前作ったやつで、サービスパックが当たっていないから?
ということで、再度回復ディスクを作り直してチャレンジ。
しかし改善しない。
ハードディスクを繋ぎ直したりしているうちに気がついたのが、データ用ドライブに昔システムが入っていて、そのバージョンを認識してエラーが出ている様子。
回復ディスクで起動するときは、システムが入る予定のドライブだけを繋ぐことで突破出来た。
(なんでこれから回復するっていうときに、別のドライブの残りかすを見てエラーにするんでしょうか、マイクロソフトさん。バックアップイメージと回復ディスクのバージョンを比較するべきでしょう)
なんとか復元対象のバックアップイメージを選択し、回復がスタートしたところですぐにエラー。
システムディスクの回復に使用できるディスクが見つかりませんディスクが見つからないとはどういうことか。
復元開始直前に、復元対象から除外するディスクを選択出来る画面があったのですが、そこでは復元先ディスクが表示されていました。
もちろん除外対象にもなっていません。
ネットで検索してみたところ、どうやらバックアップ時に接続されていたディスクの容量からサイズが減るとこのエラーが出るらしい。
このとき、バックアップ時にデータドライブが繋がっており、バックアップ対象にはしていないのに回復時に存在しないため、容量が足りないと認識されていたようだ。
(何この仕様?)
結局、バックアップを取るときにはシステムドライブと、バックアップイメージ保存ドライブだけを繋いでバックアップ。復元時は、復元先ドライブと、バックアップイメージ保存ドライブ、CD/DVDドライブだけを繋いで起動するとよいようです。
もうちょっと分かりやすい仕様になりませんかね。せめてメッセージだけでも。マイクロソフトさん。
2012/06/15
tar.bz2なバックアップファイルが復元出来なかった(解決)
tar.bz2なバックアップファイルが復元出来なかった。
bzip2recoverを使えということで、使ってみる。
コンパイルし直せとのこと。
http://www.bzip.org/
からソースをダウンロード
bzip2recover.cの真ん中ぐらいに
tar.bz2のファイルサイズは21,113,008,629なんだけど、どのくらいまで増やせば良いのだろう。
この進捗に表示されている108,490,796,940を調べてみる。
ソースを追いかけてみると、このfromとtoはbStartとbEnd、そして他の場所に
ファイルサイズをビット換算すると168,904,069,032。
8分の5ぐらいのところまで処理しているようなので、余裕を持って2倍にしてみる。
再度bzip2recoverを実行。
これを結合しつつ展開
このファイルだけを再度bzip2recoverに掛けてみたが、エラーは消えず。
結局この部分だけを破棄することとなった。
bzip2: Data integrity error when decompressing.
Input file = (stdin), output file = (stdout)
It is possible that the compressed file(s) have become corrupted.
You can use the -tvv option to test integrity of such files.
You can use the `bzip2recover' program to attempt to recover
data from undamaged sections of corrupted files.
tar: アーカイブ中に予期せぬ EOF があります
tar: アーカイブ中に予期せぬ EOF があります
tar: Error is not recoverable: exiting now
70GBのファイルを20GBまで圧縮してあるのだが、どうやら壊れてしまったようだ。bzip2recoverを使えということで、使ってみる。
block 49998 runs from 108483591327 to 108485995530 block 49999 runs from 108485995579 to 108488398408 block 50000 runs from 108488398457 to 108490796940 bzip2recover: `all0609.tar.bz2' appears to contain more than 50000 blocks bzip2recover: and cannot be handled. To fix, increase bzip2recover: BZ_MAX_HANDLED_BLOCKS in bzip2recover.c, and recompile.50000ブロック以上には対応出来ないようだ。
コンパイルし直せとのこと。
http://www.bzip.org/
からソースをダウンロード
bzip2recover.cの真ん中ぐらいに
#define BZ_MAX_HANDLED_BLOCKS 50000という記述があるので、これを増やすと良いらしい。
tar.bz2のファイルサイズは21,113,008,629なんだけど、どのくらいまで増やせば良いのだろう。
この進捗に表示されている108,490,796,940を調べてみる。
ソースを追いかけてみると、このfromとtoはbStartとbEnd、そして他の場所に
bStart[currBlock] = bitsRead;という記述があることから、ビット表記らしい。
ファイルサイズをビット換算すると168,904,069,032。
8分の5ぐらいのところまで処理しているようなので、余裕を持って2倍にしてみる。
#define BZ_MAX_HANDLED_BLOCKS 100000configureなどはないので、直接make。
再度bzip2recoverを実行。
ls rec15610all0609.tar.bz2 rec31226all0609.tar.bz2 rec46842all0609.tar.bz2 rec62458all0609.tar.bz2 rec78074all0609.tar.bz2 rec15611all0609.tar.bz2 rec31227all0609.tar.bz2 rec46843all0609.tar.bz2 rec62459all0609.tar.bz2 rec78075all0609.tar.bz2 rec15612all0609.tar.bz2 rec31228all0609.tar.bz2 rec46844all0609.tar.bz2 rec62460all0609.tar.bz2 rec78076all0609.tar.bz2 rec15613all0609.tar.bz2 rec31229all0609.tar.bz2 rec46845all0609.tar.bz2 rec62461all0609.tar.bz2 rec78077all0609.tar.bz28万近いファイルが生成された。
これを結合しつつ展開
find . -name "rec*.bz2" | sort | xargs -n1 bzcat | dd bs=65536 | tar xvf -
all0609.pgbackup
bzcat: Data integrity error when decompressing.
Input file = ./rec15012all0609.tar.bz2, output file = (stdout)
It is possible that the compressed file(s) have become corrupted.
You can use the -tvv option to test integrity of such files.
You can use the `bzip2recover' program to attempt to recover
data from undamaged sections of corrupted files.
どうやらrec15012all0609.tar.bz2がまだ壊れているようだ。このファイルだけを再度bzip2recoverに掛けてみたが、エラーは消えず。
結局この部分だけを破棄することとなった。
2012/06/10
glibc 2.15のビルドがループする(未解決)
CentOS5.8にgcc 4.7が入っている環境で、glibc 2.15をビルドしようとすると、nptlのところで延々とループしてしまう現象に遭遇した。
検索してみると、「時計が狂ってるんじゃない?アハン?」「VMだったから狂ってたよ!イエアー」みたいな感じで解決してしまっていた。
しかし、うちの場合は実マシンに直接入ってるし、dateコマンドを叩いてみても正しい時刻が返ってくる。
途方に暮れていたところ、別の検索結果から、インストール先のincludeを消すか名前を変えたら上手く行ったよ、という書き込みを発見。
/usr/localにインストールしようとしているときに、/usr/local/includeの方を参照しちゃって、まずいことになるらしい。
早速、
mv /usr/local/include /usr/local/include_org
としてconfigureしてみると、ヘッダファイルが見つからないというエラー。
そ、そうか…。
元に戻して、configureをしてから/usr/local/includeをリネーム。
すると、gd.hが見つからないというエラー。
確かに、gd.hも/usr/local/includeに入っていた。
もう一度、configure --helpを見直すと、gdのインクルードディレクトリを指定するオプションがあった。
もしかして、このために?というようなオプション。
結局、以下のような手順で問題の箇所は通過出来た。
1.ソース展開
tar jxf glibc-2.15.tar.bz2
2.展開したディレクトリに入る
cd glibc-2.15
3.ビルドディレクトリを作る
mkdir -p build
4.ビルドディレクトリに移動
cd build
5.gdのインクルードディレクトリを参照するためのシンボリックリンクを用意
ln -s /usr/local/include /usr/local/gd
6.configure
../configure --disable-sanity-checks --with-gd-include=/usr/local/gd
7.インストール先のincludeディレクトリをリネーム
mv /usr/local/include /usr/local/include_org
8.シンボリックリンクの先が居なくなってるので張り直し
rm -f /usr/local/gd
ln -s /usr/local/include_org /usr/local/gd
9.make
make
しかし、その後もmakeでエラーが頻発し、もう前にも後ろにも進めないという状態。
結局諦めた。
1.そもそもの発端は、MongoDBにアクセスするC++プログラムを書きたい。
2.標準で入っているboost 1.33では、古くてビルドが通らない。
3.boost最新版がgcc4.1でビルド出来ない。
4.gcc4.7を/usr/localに入れる。
5.phpが起動しなくなった。
6./lib64に入っているlibc.so.6(glibc 2.5由来)と/usr/local/lib64/libc.so.6(glibc 2.15由来)が衝突している(後者を読んで欲しいのに、前者が読まれる)
というようなことで、いろいろ環境を立ち直らせたかったのですが、gcc4.7はまだ早すぎたようです。
結局CentOS6.2を入れ直して標準のgccのバージョンが上がれば…と期待しつつ、システムを入れ替えることにしました。
アップグレードはサポート対象外とのことで、再インストールを予定しています。とりあえずはyumからのアップデートも試してみようかと思います。成功した報告はないらしいのですが。
検索してみると、「時計が狂ってるんじゃない?アハン?」「VMだったから狂ってたよ!イエアー」みたいな感じで解決してしまっていた。
しかし、うちの場合は実マシンに直接入ってるし、dateコマンドを叩いてみても正しい時刻が返ってくる。
途方に暮れていたところ、別の検索結果から、インストール先のincludeを消すか名前を変えたら上手く行ったよ、という書き込みを発見。
/usr/localにインストールしようとしているときに、/usr/local/includeの方を参照しちゃって、まずいことになるらしい。
早速、
mv /usr/local/include /usr/local/include_org
としてconfigureしてみると、ヘッダファイルが見つからないというエラー。
そ、そうか…。
元に戻して、configureをしてから/usr/local/includeをリネーム。
すると、gd.hが見つからないというエラー。
確かに、gd.hも/usr/local/includeに入っていた。
もう一度、configure --helpを見直すと、gdのインクルードディレクトリを指定するオプションがあった。
もしかして、このために?というようなオプション。
結局、以下のような手順で問題の箇所は通過出来た。
1.ソース展開
tar jxf glibc-2.15.tar.bz2
2.展開したディレクトリに入る
cd glibc-2.15
3.ビルドディレクトリを作る
mkdir -p build
4.ビルドディレクトリに移動
cd build
5.gdのインクルードディレクトリを参照するためのシンボリックリンクを用意
ln -s /usr/local/include /usr/local/gd
6.configure
../configure --disable-sanity-checks --with-gd-include=/usr/local/gd
7.インストール先のincludeディレクトリをリネーム
mv /usr/local/include /usr/local/include_org
8.シンボリックリンクの先が居なくなってるので張り直し
rm -f /usr/local/gd
ln -s /usr/local/include_org /usr/local/gd
9.make
make
しかし、その後もmakeでエラーが頻発し、もう前にも後ろにも進めないという状態。
結局諦めた。
1.そもそもの発端は、MongoDBにアクセスするC++プログラムを書きたい。
2.標準で入っているboost 1.33では、古くてビルドが通らない。
3.boost最新版がgcc4.1でビルド出来ない。
4.gcc4.7を/usr/localに入れる。
5.phpが起動しなくなった。
6./lib64に入っているlibc.so.6(glibc 2.5由来)と/usr/local/lib64/libc.so.6(glibc 2.15由来)が衝突している(後者を読んで欲しいのに、前者が読まれる)
というようなことで、いろいろ環境を立ち直らせたかったのですが、gcc4.7はまだ早すぎたようです。
結局CentOS6.2を入れ直して標準のgccのバージョンが上がれば…と期待しつつ、システムを入れ替えることにしました。
アップグレードはサポート対象外とのことで、再インストールを予定しています。とりあえずはyumからのアップデートも試してみようかと思います。成功した報告はないらしいのですが。
2012/04/02
カラオケボックスにおける新しい体系
わたしは音痴です。
自分の下手さ加減に、こんな歌声は聞きたくないと自分が思います。
ですので自分からカラオケに行くことはないのだけど、流れ上避けられない状況というのはあります。
そういう場合、何かと理由をつけて歌うのは断るのですが、カラオケボックスでは歌うことがメインになりすぎていて、なかなか場を白けさせずにということに気を遣います。
そこで、どういう状態がベストなのか、そこから導き出された提案を書いてみます。
こんなことをカラオケボックス内でやりとりしたくないし、それこそ場が白けるので、こんなところに書いています。
まず、なぜ音痴なのか。なぜ歌を上手くしようと思わないのか。
すべての人には得手不得手があります。そりゃ、頭の回転も良くて、記憶力も抜群、運動能力も高く、ルックスも万人受け…そんな人になりたいです。
しかし、持って生まれた身体。鍛えるにしても限界があります。
池乃めだか氏にダンクシュートをしろと言っても無理なのです。
Q:誰も聞いてないよ。
A:わたしが聞いています。
Q:歌えば気持ちいいよ。声出せば気持ちいいよ。
A:だから自分の歌声を聞きたくないのです。それならさきっちょでアメマと叫びます。
Q:出せる音域の歌を歌えばいいじゃないのか。
A:歌いたい歌を歌わずにして、何が気持ちいいのでしょうか。声が出るなら高いキーの曲を歌いたいです。
Q:歌わないと楽しくないよ。
A:他の人の上手い歌を聴いているだけで十分楽しいのです。
Q:下手でもいいじゃない。
A:わたしが苦痛になってもいいというのか。
そんなこんなで、最初にも書いたとおり、カラオケボックスは一般人にとって歌う場でしかなく(オフ会とかで、歌わずに過ごす場合もありますが、それは別にして)、歌が苦手な人にとっては苦痛な空間であることが多いです。
そこで、カラオケボックスの仕組みがもう少し変われば、みんな好き勝手なことしてて楽しめるのに、とも考えました。親交を深めるという意味では、どうなのかという気もしますが、うまく変えられればいけるのではないでしょうか。
例えば、飲み屋でハンドルキーパーは割引になるように、歌声キーパー(笑)の人が居ると、キーパーは割引、歌う人も少し割引とか。(調べてみたのだけど、最近の通信カラオケは一曲当たりの単価じゃないみたいで、店舗にメリットがない?)
カラオケの曲がビートマニア・ポップン・DDRみたいになっていて同時に遊べる。(歌声でバンゲリング帝国が操作できるとか)
なかなか上手い組み合わせが思いつきませんが、カラオケというものを別のものに進化させることができれば、もっと多くの人が楽しめる場になるのではないかと、思うのです。
2011/12/23
PostgreSQL 9.1でのパーティション全体のソートの最適化
「PostgreSQL Advent Calendar」23日目です。
PostgreSQLにはパーティショニングテーブルというものがあります。今日はそのお話。
「カラム定義が同じ複数のテーブルに、データを分割して格納できる」機能といいますか、「テーブルに親子関係を持たせられる」といいますか、詳しくは、Let's PostgreSQLを参照。(丸投げ)
拙作「ふぁぼるっく」では、バックエンドのデータベースとしてPostgreSQLを採用しています。Twitterのつぶやきデータが大量に貯まり、SSDに載りきらないため、新しいデータはSSD上のテーブルスペース、古いデータはHDD上のテーブルスペースと分けて保存しています。
そこで検索は横断的にやりたいということで、パーティショニングテーブルを使っています。
しかし、どうにも重たい。要求は新しいもの順で表示するので、SSDだけにアクセスし、データが無ければHDDを見に行くような動きをしてほしいのです。
Twitterでぼやいてみたら、9.1からは「パーティション全体のソートの最適化」が行われていることを教えてもらいました。そういえば、9.1を使っていたんだった。ということで、追試してみました。
主キーはそれぞれidの社員番号。t_child10はidが10代、t_child20は20代という制約が付いている。
そのほか、kindの役職にインデックスを張っている。
このとき
つぎに
Limit
-> Sort
Sort Key: public.t_parent.id
-> Result
-> Append
-> Index Scan using t_parent_pkey on t_parent
Filter: (kind = 2)
-> Index Scan using t_child10_kind_idx on t_child10 t_parent
Index Cond: (kind = 2)
-> Index Scan using t_child20_kind_idx on t_child20 t_parent
Index Cond: (kind = 2)
となり、全テーブルを見に行くようになってしまいました。
いろいろ試してみたのですが、テーブルの設計がかなり物を言うようです。あとは頻繁にANALYZEをかける必要がありそう。
実際に使用している環境では、一つのテーブルが数千万行、また正規化しまくっていてJOINでつないでいるテーブルも数百万行あり、 「パーティション全体のソートの最適化」が行われませんでした。
プランナが賢くなるまで、もう少し辛抱のようです。
24日目はt_motookさんの「SQLFeatureNotSupportedException - JDBC4.0 API の中で未実装のもの」です。
PostgreSQLにはパーティショニングテーブルというものがあります。今日はそのお話。
「カラム定義が同じ複数のテーブルに、データを分割して格納できる」機能といいますか、「テーブルに親子関係を持たせられる」といいますか、詳しくは、Let's PostgreSQLを参照。(丸投げ)
拙作「ふぁぼるっく」では、バックエンドのデータベースとしてPostgreSQLを採用しています。Twitterのつぶやきデータが大量に貯まり、SSDに載りきらないため、新しいデータはSSD上のテーブルスペース、古いデータはHDD上のテーブルスペースと分けて保存しています。
そこで検索は横断的にやりたいということで、パーティショニングテーブルを使っています。
しかし、どうにも重たい。要求は新しいもの順で表示するので、SSDだけにアクセスし、データが無ければHDDを見に行くような動きをしてほしいのです。
Twitterでぼやいてみたら、9.1からは「パーティション全体のソートの最適化」が行われていることを教えてもらいました。そういえば、9.1を使っていたんだった。ということで、追試してみました。
PostgreSQLで期間ごとに区切ってパーティショニングテーブルを使っているんだけど、その期間をORDER BYに入れた場合、小さい部分の受け持ちテーブルから順に見に行ってくれたりするんだろうか?いやー、この遅さなら、見てくれてないんだろうな。
— おさ (@osapon) 12月 15, 2011
たとえば、Twitterのstatus_idの大きい順に指定件数だけ取ってきたいんだけど、古いテーブルも見てるんならやっぱり遅いよな。アプリ側で各テーブルを順に見て、指定件数分取得できるまで古いテーブルを掘り返す方が速いんだろうか。
— おさ (@osapon) 12月 15, 2011
それってアプリ側でやることじゃないよなぁ。せっかく制約も掛けて、そのテーブルに含まれるstatus_idが分かってるんだからさ。
— おさ (@osapon) 12月 15, 2011
EXPLAINの結果はどうでしょうか? 9.1ではパーティションのORDER BYが強化されています→ bit.ly/q5jnOV RT @osapon: 期間ごとに区切ってパーティショニングテーブルを使っているんだけど、その期間をORDER BYに入れた場合…
— 日本PostgreSQLユーザ会 (@PostgreSQL_JP) 12月 15, 2011
@PostgreSQL_JP 9.1を使っているんですが、他のテーブルとJOINしたりしてるので、そのせいか全テーブルを見に行っちゃってるんですよね。条件減らして、JOINしなければうまくソートしてくれました。もう少しSQLを調整してみます。
— おさ (@osapon) 12月 15, 2011
@osapon なるほどなるほど。他のテーブルも含めた絞り方がキーなんですね。
— 日本PostgreSQLユーザ会 (@PostgreSQL_JP) 12月 15, 2011
PostgreSQL.1の「パーティション全体のソートの最適化」が無効になる条件判明。SELECT a.*,b.* FROM A JOIN B ON ~ WHERE B.hoge ORDER BY A.idでB.hogeにインデックスが無い時。うー、その項2値しか入らないんよ。
— おさ (@osapon) 12月 15, 2011
試してみた環境はPostgreSQL9.1.2、テーブル構成はこんな感じ。CREATE TABLE t_parent ( id smallint NOT NULL, -- 社員番号 kind smallint NOT NULL, -- 役職 fullname text NOT NULL, -- 名前 CONSTRAINT t_parent_pkey PRIMARY KEY (id ) ) WITH ( OIDS=FALSE ); ALTER TABLE t_parent OWNER TO postgres; COMMENT ON COLUMN t_parent.id IS '社員番号'; COMMENT ON COLUMN t_parent.kind IS '役職'; COMMENT ON COLUMN t_parent.fullname IS '名前'; CREATE TABLE t_child10 ( -- 継承 from table t_parent: id smallint NOT NULL, -- 継承 from table t_parent: kind smallint NOT NULL, -- 継承 from table t_parent: fullname text NOT NULL, CONSTRAINT t_child10_pkey PRIMARY KEY (id ), CONSTRAINT id_chk_1 CHECK (id >= 10 AND id < 20) ) INHERITS (t_parent) WITH ( OIDS=FALSE ); ALTER TABLE t_child10 OWNER TO postgres; CREATE INDEX t_child10_kind_idx ON t_child10 USING btree (kind ); CREATE TABLE t_child20 ( -- 継承 from table t_parent: id smallint NOT NULL, -- 継承 from table t_parent: kind smallint NOT NULL, -- 継承 from table t_parent: fullname text NOT NULL, CONSTRAINT t_child20_pkey PRIMARY KEY (id ), CONSTRAINT id_chk_2 CHECK (id >= 20 AND id < 30) ) INHERITS (t_parent) WITH ( OIDS=FALSE ); ALTER TABLE t_child20 OWNER TO postgres; CREATE INDEX t_child20_kind_idx ON t_child20 USING btree (kind ); INSERT INTO t_child10 VALUES (10, 1, '社長'); INSERT INTO t_child10 VALUES (11, 2, '部長A'); INSERT INTO t_child10 VALUES (12, 2, '部長B'); INSERT INTO t_child10 VALUES (16, 3, '課長A'); INSERT INTO t_child10 VALUES (19, 4, '社員A'); INSERT INTO t_child20 VALUES (25, 2, '部長C'); INSERT INTO t_child20 VALUES (23, 3, '課長B'); INSERT INTO t_child20 VALUES (27, 3, '課長C'); INSERT INTO t_child20 VALUES (24, 4, '社員B'); INSERT INTO t_child20 VALUES (26, 4, '社員C'); INSERT INTO t_child20 VALUES (28, 4, '社員D');親テーブルt_parent、子テーブルt_child10、t_child20。
主キーはそれぞれidの社員番号。t_child10はidが10代、t_child20は20代という制約が付いている。
そのほか、kindの役職にインデックスを張っている。
このとき
EXPLAIN (COSTS OFF) SELECT * FROM t_parent WHERE id >= 15 ORDER BY id LIMIT 2
とidが15以上の者、id順で上位2件を取得すると
Limit
-> Result
-> Merge Append
Sort Key: public.t_parent.id
-> Index Scan using t_parent_pkey on t_parent
Index Cond: (id >= 15)
-> Index Scan using t_child10_pkey on t_child10 t_parent
Index Cond: (id >= 15)
-> Index Scan using t_child20_pkey on t_child20 t_parent
Index Cond: (id >= 15)
となる。このMerge Appendが最適化が行われた状態。
Limit
-> Result
-> Merge Append
Sort Key: public.t_parent.id
-> Index Scan using t_parent_pkey on t_parent
Index Cond: (id >= 15)
-> Index Scan using t_child10_pkey on t_child10 t_parent
Index Cond: (id >= 15)
-> Index Scan using t_child20_pkey on t_child20 t_parent
Index Cond: (id >= 15)
となる。このMerge Appendが最適化が行われた状態。
つぎに
EXPLAIN (COSTS OFF) SELECT * FROM t_parent WHERE kind = 2 ORDER BY id LIMIT 2とkindが2の者、id順で上位2件を取得すると
Limit
-> Sort
Sort Key: public.t_parent.id
-> Result
-> Append
-> Index Scan using t_parent_pkey on t_parent
Filter: (kind = 2)
-> Index Scan using t_child10_kind_idx on t_child10 t_parent
Index Cond: (kind = 2)
-> Index Scan using t_child20_kind_idx on t_child20 t_parent
Index Cond: (kind = 2)
となり、全テーブルを見に行くようになってしまいました。
(追記9:53 ANALYZEかけたらMerge Appendになりました。)
いろいろ試してみたのですが、テーブルの設計がかなり物を言うようです。あとは頻繁にANALYZEをかける必要がありそう。
実際に使用している環境では、一つのテーブルが数千万行、また正規化しまくっていてJOINでつないでいるテーブルも数百万行あり、 「パーティション全体のソートの最適化」が行われませんでした。
プランナが賢くなるまで、もう少し辛抱のようです。
24日目はt_motookさんの「SQLFeatureNotSupportedException - JDBC4.0 API の中で未実装のもの」です。
2011/12/03
zabbixで外部チェックアイテムを作る
(この記事はzabbix 1.8を対象としたものです。2.0以降では、下記パラメータの1番目にホスト名というのがありません)
サーバの状態監視にはzabbix!
便利すぎます。結構負荷高いのが難点だけど、余裕があったら監視用サーバを立てるのもありかなと思う。
普段はテンプレートをそのまま適用して、動いていないサービスのアイテムだけ解除していく使い方をしているのだけど、テンプレートで用意されていない物を監視したいときに、外部チェックアイテムを作成して対応した。
アイテムのタイプ:外部チェック
キー:get_queue_count.sh[fav_queue]
などとする。
このとき、zabbix_server.confのExternalScriptsに、キーで指定したスクリプトのパスを書いておく。
そしてスクリプト側。[ ]で括られた部分がパラメータとして渡されるのだけど、パラメータの1番目にホスト名が自動的に付けられる。
上の例だと、実際に呼ばれるコマンドは
get_queue_count.sh hostname fav_queue
みたいに。
なので、スクリプト側では、それを考慮しておく必要がある。
#/bin/bash
/usr/bin/mongo --quiet --eval="db.$2.count()" favlook
という感じで、ホスト名は無視した。
サーバの状態監視にはzabbix!
便利すぎます。結構負荷高いのが難点だけど、余裕があったら監視用サーバを立てるのもありかなと思う。
普段はテンプレートをそのまま適用して、動いていないサービスのアイテムだけ解除していく使い方をしているのだけど、テンプレートで用意されていない物を監視したいときに、外部チェックアイテムを作成して対応した。
アイテムのタイプ:外部チェック
キー:get_queue_count.sh[fav_queue]
などとする。
このとき、zabbix_server.confのExternalScriptsに、キーで指定したスクリプトのパスを書いておく。
そしてスクリプト側。[ ]で括られた部分がパラメータとして渡されるのだけど、パラメータの1番目にホスト名が自動的に付けられる。
上の例だと、実際に呼ばれるコマンドは
get_queue_count.sh hostname fav_queue
みたいに。
なので、スクリプト側では、それを考慮しておく必要がある。
#/bin/bash
/usr/bin/mongo --quiet --eval="db.$2.count()" favlook
という感じで、ホスト名は無視した。
登録:
投稿 (Atom)




