Archive for 6月, 2007

ネタフルさんでtmitterを紹介していただきました

2007年06月29日 written by fjkktkys

[N] 日本語が使えてメールでTwitterを更新/確認できる「tmitter」

tmitter_logo

ネタフルさんでtmitterを紹介していただきました。
紹介していただいて非常に嬉しいのですが、リンクが全くなかったりして非常に残念だったりもします。

tmitterですが、システム的な粗が色々と見えて来たので、そのうちその辺も強化したいものです。
今後ともtmitterをよろしくお願いします。

(追記)
リンクをはっていただきました。
ありがとうございます!

tmitterにReplies取得機能を実装しました

2007年06月13日 written by fjkktkys

tmitter_logo

tmitterアップデートのお知らせです。

Repliesを取得する機能を実装しました。
件名に「r」です。

詳細は、tmitterよりご覧ください。

今後ともtmitterをよろしくお願いします。

Mac OSXにPostgreSQLをインストールしたメモ

2007年06月10日 written by fjkktkys

マシンのスペックが
iBook G4 1.07GHz PowerPC
OSX10.4.9

以下のサイトからパッケージを取ってきて、
PostgreX_Package.mpkgというパッケージを実行して再起動。
PostgreX - PostgreSQL Easy Installer for Mac OSX

CODE:
  1. # ps aux | grep postgres

とやると4つぐらいプロセスが立ち上がっている。
initdbとかはパッケージ側でやってくれてます。

自分のアカウントから、PostgreSQLを操作できるようにしておきたい。
自分のアカウント(ここでは、myaccount)をPostgreSQLのスーパーユーザーとして作成。

CODE:
  1. # su postgres
  2. # /usr/local/pgsql/bin/createuser -s myaccount
  3. # exit

/usr/local/pgsql/binのパスを通します。
(使用しているシェルとかエディタによって違うので略)

とりあえず、アカウント名のデータベースを作っておく。

CODE:
  1. # createdb myaccount

そしたら

CODE:
  1. # psql

で、対話インターフェースに入れます。
データベースを指定していないと自動でmyaccountに繋がってます。
(というか常に指定するなら、createdb myaccountは不要。
 MySQLでmysqlとだけ打つことがあるので、とりあえずこうしました)

PostgreX - PostgreSQL Easy Installer for Mac OSX
のパッケージが素晴らしいですね。
initdbとかの初期設定いらずというのが助かります。

PHPのPDOのprepareについて

2007年06月09日 written by fjkktkys

スクリプトのprepareとサーバのprepare

PHPのPDOを使いながらクエリーログを見ていたら、
見慣れないものが目に入ってきました。

CODE:
  1. 391 Connect     admin@localhost on pdo_test
  2. 391 Prepare     [1] INSERT INTO users SET name = ?
  3. 391 Execute     [1] INSERT INTO users SET name = '9f732d76d9f2f0b4e62c8091c99a2334'
  4. 391 Quit

Prepareという行なのですが、PerlのDBIを使っていた分には見たことがありませんでした。

そこで以下を参照して、
MySQL 関数 (PDO_MYSQL)

CODE:
  1. $pdo = new PDO('mysql:host=localhost;dbname=pdo_test;charset=utf-8;unix_socket=/tmp/mysql.sock', "username", "password");
  2. $pdo->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, true);

上のようにPDOの設定をして同じSQLを実行すると

CODE:
  1. 392 Connect     admin@localhost on pdo_test
  2. 392 Query       INSERT INTO users SET name = 'f071c916f507876b8f67735faa0e015f'
  3. 392 Quit

いつものようなログが取れましたとさ。

ここで認識できるのは、スクリプト側でのprepareとMySQLサーバサイドでのprepareが別物だということ。恥ずかしながらそうとも知らずに今までPerlのDBIでprepareを使っておりました。
(prepareを使う理由は、プレースホルダーを使って外部入力を安全にSQLに挿入するためです。)

ベンチマークしてみる

で、以下のようなSQLを用意して、
init.sql

CODE:
  1. USE pdo_test;
  2.  
  3. DROP TABLE IF EXISTS users;
  4. CREATE TABLE users (
  5.     id   INT(16) PRIMARY KEY AUTO_INCREMENT,
  6.     name VARCHAR(32) UNIQUE NOT NULL
  7. );

以下のような、スクリプトを用意します。
pdo_test.php

CODE:
  1. <?php
  2. $pdo = new PDO('mysql:host=localhost;dbname=pdo_test;charset=utf-8;unix_socket=/tmp/mysql.sock', "username", "password");
  3. //$pdo->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, true);
  4.  
  5.  
  6.  
  7. //foreach ( range(1, 100000) as $i) {
  8. insertByPrepare($pdo);
  9. //insertByQuery($pdo);
  10. //}
  11.  
  12. //insertByPrepareLoop($pdo);
  13.  
  14. function insertByPrepare ($pdo) {
  15.     $sth = $pdo->prepare("INSERT INTO users SET name = ?");
  16.     $sth->execute( array(hash('md5', microtime())) );
  17. }
  18.  
  19. function insertByQuery ($pdo) {
  20.     $pdo->query("INSERT INTO users SET name = '" . hash('md5', microtime()) . "'");
  21. }
  22.  
  23. function insertByPrepareLoop ($pdo) {
  24.     $sth = $pdo->prepare("INSERT INTO users SET name = ?");
  25.     foreach ( range(1, 100000) as $i) {
  26.         $sth->execute( array(hash('md5', microtime())) );
  27.     }
  28. }
  29. ?>

ベンチマークには疎いので、適当で手動なんですが、
このスクリプトのコメントアウトのあたりを外したりつけたりして、
コマンドラインから以下を繰り返しです。

CODE:
  1. # mysql <init.sql
  2. # time php pdo_test.php

結果

当たり前ですが、prepareしたステートメントハンドラをループで回すという、
prepareの意味通りに使うパターンが一番早くなりました。

insertByQuery [PDO::MYSQL_ATTR_DIRECT_QUERY, true]
php pdo_test.php  10.14s user 4.24s system 32% cpu 44.907 total

insertByQuery
php pdo_test.php  13.83s user 8.65s system 33% cpu 1:07.68 total

insertByPrepareLoop [PDO::MYSQL_ATTR_DIRECT_QUERY, true]
php pdo_test.php  8.48s user 4.03s system 30% cpu 41.258 total

insertByPrepareLoop
php pdo_test.php  8.14s user 4.40s system 30% cpu 40.570 total

insertByPrepare [PDO::MYSQL_ATTR_DIRECT_QUERY, true]
php pdo_test.php  12.84s user 4.34s system 34% cpu 49.931 total

insertByPrepare
php pdo_test.php  18.05s user 10.15s system 36% cpu 1:17.68 total

ループを回さないところでprepareをすると少し遅いようです。
基本的に「PDO::MYSQL_ATTR_DIRECT_QUERY, true」にしておいて、サーバ側でprepareしないようにしておくと良さそうですね。

#余談
PHP5.1.xだと、LIMITなどで

CODE:
  1. $sth = $pdo->prepare('SELECT * FROM users LIMIT ?');

とやるとステートメントハンドラ自体が帰ってきません。
5.2.xでは解決されているバグのようです。

DBにJSONを突っ込む

2007年06月08日 written by fjkktkys

データベースの1カラムに配列を突っ込むのはお作法的にはあまりよろしくなくて、デリミタとして[|,]あたりを使ってカラムに突っ込んだりした過去もあった。

先日、それPHPのserialize関数でやってるよという話を聞いて割と目から鱗だった。連想配列も気軽につっこめます!でもPerlで読めないよ><みたいな話だった。

CPANモジュールを探したら案の定ありました。
The CPAN Search Site - search.cpan.org PHP::Serialization
Perlからも安心してPHPのserializeを扱えます。

でも時代はJSONでしょうとうことで、以下の記事とかを参照すると
よほど階層を深くしない限りは問題ない感じだ。
zuzara : PHP5.2.0でserialize()とjson_encode()はどちらが速いのか

バッドノウハウですが、DBに配列などを突っ込む時はJSONがよろしいようで。