カテゴリー : 2007年 11月

パフォーマンスチューニング


http://www.asahi-net.or.jp/~aa4t-nngk/pgsql5.html
 
もともと自分用メモとして書き始めたとのことですが、
読みやすく書かれている良書です。
 
参考:
- Linux Memo(PostgreSQL) (Stray Penguin)

cygwin で nice


nice / renice を使うと起動するプロセスや起動済のプロセスの優先度を変更することができます。
 
nice の書式:

nice [-n 数値 ] 実行するコマンド [引数] ..

例:

$ nice -n 10 sleep 100 # nice 10 sleep 100 は間違い

 
renice: の書式:

renice 数値 [ [-p] PID ] [ [-g] pgrps] [ [-u] ユーザ]

指定した PID (またはプロセスグループ(PGID)、ユーザ)のプロセスの優先度を指定した数値に基づいて変更します。
Cygwin で実行する場合、PID にはWindows 上の実 PID (WINPID)ではなく、Cygwin で ps すると見られる仮想 PID を指定します。
 
例1: PID で指定

$ sleep 50 &
[1] 1448
$ renice 10 -p 1448

例2: PGID で指定

$ ps
      PID PPID PGID WINPID TTY UID STIME COMMAND
     2264 2248 2264 316 con 11363 13:31:29 /usr/bin/sleep
     2168 2248 2168 2168 con 11363 13:31:33 /usr/bin/bash
     2948 2168 2168 2920 con 11363 13:31:33 /usr/bin/sleep
$ renice 19 -g 2168 # PGID が 2168 の全てのプロセスが対象

例3: ユーザ名で指定( cygwin 経由で起動しているプロセスのうち実行ユーザが john のプロセス全ての優先度を -10 (通常以上)にする)

$ renice -10 -u john

 
Windows XP で実行した場合のプロセス優先度の対応表:

nice -n プロセス優先度
12以上
4 〜 11 通常以下
-4 〜 3 通常
-12 〜 -5 通常以上
-19 〜-13
-20 以下 リアルタイム

参考:
-起動するプログラムの優先度を変更する方法(@IT)
タスクマネージャを使った変更方法と、cmd.exe の start コマンドを使った優先度指定方法についてかかれています。

文字列への文字単位のアクセスで波括弧が非推奨にかわった


ふと PHP のドキュメントを眺めていたら、次のように書かれていました
PHP: 文字列(English)

注意: $str{42} のように波括弧を使用してアクセスすることも可能です。 しかし、角括弧を使用する方法のほうが推奨されます。 なぜなら、{波括弧} 形式は PHP 6 で廃止される予定だからです。
 
Note: They may also be accessed using braces like $str{42} for the same purpose. However, using square array-brackets is preferred because the {braces} style is deprecated as of PHP 6.

PHP5 リリース前は

$str = “foo”; echo $str[0];

が非推奨で

$str = “foo”; echo $str{0};

が推奨されていましたが、方針転換をしたようです。
 
参考:
- 2004 年 3 月のマニュアル同項(English)(archive.org)

波括弧の後に任意の文字をゼロから始まるオフセットで指定することに より、文字列内の文字にアクセスすることが可能です。
 
    注意: 過去の互換性のため、配列括弧を使用することが可能です。しかし、 この構文はPHP 4に依存しています。
    
 Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string in curly braces.
  
    Note: For backwards compatibility, you can still use array-braces for the same purpose. However, this syntax is deprecated as of PHP 4.

以前はこうなっていました。

最新版の ffmpeg をダウンロードするには


以前 ffmpeg クライアントを探し回った事があったため、配布サイトをまとめてみました。
 
- ffmpeg.org
公式サイト。
 
Windows用のffmpegバイナリは以下のサイトで配布されています。
 
- お気に入りの動画を携帯で見よう
SVN の HEAD を追いかけて Windows 用にビルドしたバイナリを配布しているサイト。
MingW での ffmpeg のビルド方法や依存するライブラリについても書かれています。
 
- ImageMagick
ImageMagick は一部のビデオフォーマットを扱うために ffmpeg を使っているため、ffmpeg.exe をバンドルしています。
Windowsユーザでインストーラが不要な方はImageMagickのFTPサーバから、実行ファイルだけのダウンロードもできます。ファイル名が”ImageMagick-(バージョン番号)-Q16-windows.zip”のものがインストーラなし版です。
 
携帯動画変換君
ffmpegのインターフェイスとして動作するソフトです。ffmpeg が同梱されていますが、2010年9月現在、何年も更新されていないためバージョンは古めの様子。
 


Linux用 RPM は http://packages.sw.be/ffmpeg/ で最新版が順次配布されているようです。

バグパターン – switch のデータ型は複数種類にすると予期しない結果になる


まずはサンプルコードを見て、結果を予想してみてください。

<?php
$result = true;
switch($result){
  case “error”: // エラー
    echo “failure”;
    exit;
  case “ok”: // 成功
  case true: //
    echo “success”;
    exit;
  default:
    echo “unexpected”;
    exit;
}
?>

一見、このコードを実行すると success が出力されるように思いますが、実際に実行してみると意外なことに failure が出力されてしまいます。
PHP の switch 文は、switch の引数と case で指定した値とを= ではなく) でチェックしているため、switch 引数が複数の種類の型になる場合は型変換などにより予想外の値と一致することになってしまうのが原因です。
 
実際どの値が何と一致するかについては以下の検証コードを実行してみると分かります。

// 検証コード:
<?php
// values to test
$targets = array(
   0,
   1,
   true,
   false,
   null,
   ”",
   ”0.00e5″,
   ”10f”,
   ”0f”,
   array(),
   array(1),
   array(“key”=>”foo”),
);
 
// —-
foreach($targets as $target){
  if(is_bool($target))
      $s = $target? “true”: “false”;
  elseif(is_null($target))
      $s = “null”;
  elseif(is_string($target))
      $s = “‘{$target}’”;
  else
      $s = $target;
  echo $s .”(“.gettype($target).”)”.”:\t”;
  switch($target){ //”0.00e5″
    case ‘a’: echo “case a”; break;
    case ‘b’: echo “case b”; break;
    case ’0′: echo “case zero”; break;
    case 10: echo “case int 10″; break;
    case 0: echo “case int 0″; break;
    default: echo “default”; break;
  }
  echo “\n”;
}

php 4.4.6 および php 5.2.3 で試したところ、実行結果次のようになりました。

0(integer): case a
1(integer): default
true(boolean): case a
false(boolean): case zero
null(NULL): case int 0
”(string): case int 0
’0.00e5′(string): case zero
’10f’(string): case int 10
’0f’(string): case int 0
Array(array): default
Array(array): default
Array(array): default

同じ empty 値でも 0, null, false, “” で結果が全く異なってしまいました。
また、 == について挙げられる数値文字列の比較時の問題(“0.00e5″ == “0″ が真になる,など)の影響も受けてしまっています。
 
この問題は、型チェックを厳密にしたり、strval(), intval() などで明示的に文字列,数値キャストを行い、switch 文の引数の型が一種類になることを保証することである程度回避できます。
しかし依然として数値として有効な文字列同士の比較の問題があるため、数値を含む文字列について正確さが必要な場合や、本当に複数型を判別させたい場合は= 演算子を使い if – elseif – else を使うほうが賢明でしょう。

if($result = true || $result= “ok”){
  echo “success”;
}elseif(empty($result) || $result
= “error”){
  // empty($result) は以下の式と等価。
  // ( !isset($result) || ($result= false || $result = null ||
  // $result= “” || $result = 0 )
  echo “failure”;
}else{
  echo “unexpected”;
}

 
参考:
- switch 構文(php.net)
- 比較演算子(php.net)
- strval()(php.net)

手描き地図検索


http://www.chiztek.net/
ペンツールで範囲を描くとその中の店を検索してくれます。
 
地図 API には Microsoft Virtual Earth を利用しているようです。
参考:
- PostGIS応用例:オンザフライの経緯度データが特定ポリゴンに含まれるかを調べる方法(ここギコ)

SQL 基礎 – JOIN (表結合)の意味の違い


SQL 標準では JOIN 句による結合構文は次のような種類があります。

INNER JOIN
LEFT OUTER JOIN
RIGHT OUTER JOIN
CROSS JOIN

LEFT JOIN, RIGHT JOIN など、よく使われる構文は上記の省略形です。

・ただの JOIN は INNER JOIN の省略形。
・LEFT JOIN は LEFT OUTER JOIN の省略形。
・RIGHT JOIN は RIGHT OUTER JOIN の省略形。

それぞれの JOIN 構文の意味は次のとおりです。

 

INNER JOIN: 内部結合

指定したカラムについて同じ値を持つレコード同士を結びつける。
内積なので指定したカラムの値がどちらかにしかないレコードについては結果に含まれません。

SELECT * FROM table1 INNER JOIN table2 USING(id)

は、次の SQL 文と同じ結果になります。

SELECT * FROM table1, table2 WHERE table1.id = table2.id

 

LEFT OUTER JOIN: 外部結合

左のテーブルを基準にして、指定したカラムについて同じ値を持つレコード同士を結びつける。
値が右のテーブルにあり左のテーブルにない場合は INNER JOIN 同様結果に含まれませんが、
値が左のテーブルにあり右のテーブルにない場合は INNER JOIN と異なり 右のテーブルのカラムには全て NULL がパディングされ、結果に含まれます。
 
このため、

SELECT * FROM table1 LEFT OUTER JOIN table2 USING(id) WHERE table2.id IS NULL

は、

SELECT * FROM table1 INNER JOIN table2 USING(id)

と同じ結果になります。
 

RIGHT OUTER JOIN: 外部結合

LEFT OUTER JOIN の左右の意味を入れ換えたもの。

SELECT * FROM table1 RIGHT OUTER JOIN table2 USING(id)

SELECT * FROM table2 LEFT OUTER JOIN table1 USING(id)

と同じ結果になります。
 

CROSS JOIN: 交差結合

ON, USING で条件を指定しない場合、左右のテーブルの直積を返します。
つまり、左右のテーブルにそれぞれ2行のレコード、3行のレコードが格納されている場合、結合結果は全てのレコードの組合せになり合計 2×3=6 行のレコードになります。
PostgreSQL や MySQL では ON, USING を指定すると INNER JOIN と等価になります。

SELECT * FROM table1 CROSS JOIN table2

は次の SQL 文と等価です。

SELECT * FROM table1, table2

また、PostgreSQL, MySQL では

SELECT * FROM table1 CROSS JOIN table2 USING(id)

は次の SQL 文と等価です。

SELECT * FROM table1 INNER JOIN table2 USING(id)

 

■ON, USING, NATURALによる結合条件指定

CROSS JOIN をのぞき、JOIN 句には ON, USING, NATURAL のいずれかを指定します。

INNER JOIN … ON 結合条件
INNER JOIN … USING(結合カラム, … )
NATURAL INNER JOIN …

 

ON:

WHERE 句と同じ書式で結合条件を絞り込む。
書式:

SELECT … FROM table1 JOIN table2 ON 条件式

table1, table2 のidが同じカラム同士を結合したい場合は次のようにします。

SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id

AND, OR など複雑な条件で絞り込む事も可能です。

SELECT * FROM table1 AS t1
  LEFT JOIN table2 AS t2 ON (
    (t1.id = t2.id OR t1.name = t2.name)
    AND t1.salary >= t2.age * 1000
  )

ON に指定する結合条件には、 WHERE 同様どんな条件式でも指定することが可能ですが、テーブル結合に関係のない条件式はWHERE句に書くようにしましょう。
 

USING:

カラム名で結合条件を絞り込む。
書式:

SELECT … FROM table1 JOIN table2 USING(カラム1 , カラム2, …)

両方のテーブルに同じカラム名がある場合に有効です。

SELECT * FROM table1 LEFT JOIN table2 USING(id)

SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id

と同等です。複数指定した場合は全てのカラムの値が一致するレコードを結合します。
 

NATURAL:

両方のテーブルを比較して名前が同じ全てのカラムを結合条件にして絞り込む。
書式:

SELECT … FROM table1 NATURAL JOIN table2

USING に両テーブルの共通カラムを全て指定したものと同じです。すなわち、

SELECT * FROM table1 NATURAL LEFT JOIN table2

は、両方のテーブルに id, name, age が存在する場合、

SELECT * FROM table1 LEFT JOIN table2 USING (id, name, age)

を指定したのと同等の結果になります。
 

■複数のJOIN句を組み合わせる

3つ以上のテーブルを複数のJOIN 句で結合する事もできます。
例として、table1, table2. table3 全てのテーブルに同じidが存在するレコードのみ抽出する場合は次のようになります。

SELECT * FROM table1
  INNER JOIN table2 USING(id)
  INNER JOIN table3 USING(id)

複数のJOIN を組み合わせる時の結合順序は左から順に評価されます。結合順序を制御したい場合、カッコが使用できます。

SELECT * FROM table1 AS t1
  LEFT JOIN ( table2 AS t2 INNER JOIN table3 USING(id)) ON t1.value = t2.tag
)

この例では table2, table3の同じidのレコードをINNER JOIN 句を使い結合し、その後 table1 と LEFT JOIN 句で結合されます。
 

参考:

- SELECT(PostgreSQL 8.2.5 マニュアル)
- MySQL 5.1 リファレンスマニュアル 12.2.7.1 JOIN 構文(MySQL AB)
- SQLite が認識できるクエリー言語
- 特殊な結合演算子 SQL(TELCHSCORE by 4DD)
- SQL92

テーブルのディスク使用量を取得する


SELECT relname, relfilenode, relpages FROM pg_class;

relname がテーブル名、relfilenode が実体ファイル名、 relpages が利用しているページ数概算。1ページは通常 8KB です。
 

SELECT c2.relname, c2.relpages
    FROM pg_class c, pg_class c2, pg_index i
    WHERE c.oid = i.indrelid
        AND c2.oid = i.indexrelid
    ORDER BY relpages DESC;

同様にインデックスの利用しているページ数を取得します。
 
参考:
- ディスク使用量の監視(PostgreSQL 8.2.5 公式マニュアル)
- pg_class(同上)

アクセス中のファイルに対する他のプロセスでのファイル読み書き禁止を制御する


.NET, C++ ともに FileStream 等でのファイルアクセス時に FileShare という列挙体のメンバを追加で指定することでロック制御することができます。
 
http://msdn2.microsoft.com/ja-jp/library/system.io.fileshare(VS.80).aspx より引用:

FileShare 列挙体のメンバ
 
Delete:
  後続のファイルの削除を許可します。
Inheritable:
  ファイル ハンドルを子プロセスで継承できるようにします。Win32 では、直接サポートされません。
None:
  現在のファイルの共有を解除します。ファイルを閉じるまで、このプロセスまたは別のプロセスがファイルを開く要求をしても失敗します。
Read:
  後続の読み取り用のファイルを開くことを許可します。このフラグが指定されていない場合は、ファイルを閉じるまで、このプロセスまたは別のプロセスが読み取り用のファイルを開く要求をしても失敗します。ただし、このフラグが指定されていても、ファイルにアクセスするために追加のアクセス許可が必要になることがあります。
ReadWrite:
  後続の読み取り用または書き込み用のファイルを開くことを許可します。このフラグが指定されていない場合は、ファイルを閉じるまで、このプロセスまたは別のプロセスが読み取り用または書き込み用のファイルを開く要求をしても失敗します。ただし、このフラグが指定されていても、ファイルにアクセスするために追加のアクセス許可が必要になることがあります。
Write:
  後続の書き込み用のファイルを開くことを許可します。このフラグが指定されていない場合は、ファイルを閉じるまで、このプロセスまたは別のプロセスが書き込み用のファイルを開く要求をしても失敗します。ただし、このフラグが指定されていても、ファイルにアクセスするために追加のアクセス許可が必要になることがあります。

参考:
- FileShare 列挙体(System.IO)
- 開くファイルへの他のプロセスからのアクセスを制限する(dobon.net)

ひこにゃんに学ぶ著作権


今朝ニュースを見ていたら、第二のおふくろさん騒動ともいえるニュースが流れていました。
 
ひこにゃんピンチ!…作者、彦根市に使用中止求める(YOMIURI ONLINE) より引用:

もへろんさん(22)が「適正なキャラクター管理を怠った」などとして、市と同祭実行委員会に祭終了後の使用中止を求める調停を彦根簡裁に申し立てたが、市は9日、ひこにゃんを今後も市のマスコットとして使用すると発表した。
 
 実行委は祭のキャラクターとして2006年1月、もへろんさんが応募したネコをモチーフにした3種類の図柄を採用。実行委が許可した団体の出版物などへの利用を許可してきた。
 
 しかし、申立書によると、実行委は「お肉が好物」「特技はひこにゃんじゃんけん」など作者の意図しないひこにゃんの性格づけをしたと主張。粗悪品が出回りかねないのに無制限に使用を承認しているなどとしている。

 
財産権である著作権を持つ彦根市に対して、作者のもへろん氏が著作者人格権のうちの同一性保持権を行使している形ですね。
 
著作権は譲渡可能ですが、著作者人格権は Wikipedia の言葉を借りると「一身専属性を有する権利であるため他人に譲渡できない」権利であるとされているため、勝手な性質の追加に対して異義を唱える事は妥当である、と思います。
 
しかし、前述の記事のように「祭終了後の使用中止を求め」たり、スポニチアネックスの記事にあるように、営利目的の利用や対して「相当額の支払いを求め」たりということまで要求できるかは、祭以外の利用や営利目的の利用が、著作者の名誉声望を害するかは微妙なところではないでしょうか。
 
今回の事例が教えてくれることは、クリエイター、デザイナー、エンジニアなど個人と企業の間での契約では、個人が作成した成果物の著作権は企業が所有する、という契約が多いと思いますが、この契約上でも個人が著作物に対して著作者人格権を行使することができるということです。
 
 ちなみに、プログラムについては「特定のコンピュータで利用できるようにしたり、より効果的に利用し得るようにするために必要な改変(Wikipedia)」であれば同一性保持権でいう改変にはあたりません。
 
とりあえず彦根市の問題については、ひこにゃんは個人的にも好きなキャラクターですし、町興し成功の好例なので、当事者間でうまく話がまとまるといいなと思っています。
参考:
- 著作権法(Wikipedia)
- 著作者人格権