2015年1月8日木曜日

shとbashで文字列置換

シェルスクリプトで文字列を置換したい際、sed, per -pe などを使う手法が紹介されることが多い。が、実はこれらの外部コマンドを使わなくても、以下のように変数展開をすることでシェル内部で文字列置換をすることができちゃいます。

$ {変数名#パターン} → 前方一致でのマッチ部分削除(最短マッチ)
$ {変数名##パターン} → 前方一致でのマッチ部分削除(最長マッチ)
$ {変数名%パターン} → 後方一致でのマッチ部分削除(最短マッチ)
$ {変数名%%パターン} → 後方一致でのマッチ部分削除(最長マッチ)
$ {変数名/置換前文字列/置換後文字列} → 文字列置換(最初にマッチしたもののみ)
$ {変数名//置換前文字列/置換後文字列} → 文字列置換(マッチしたものすべて)
#!/bin/bash

echo "実行スクリプト ファイルパス : " ${0%/*}
echo "実行スクリプト ファイル名   : " ${0##*/}
echo

PATH=home/to/path/file.ext
echo 'PATH='${PATH}
echo
echo '${PATH#*/} : '${PATH#*/} 
echo '${PATH##*/}: '${PATH##*/}
echo '${PATH%/*} : '${PATH%/*} 
echo '${PATH%%/*}: '${PATH%%/*}
echo '${PATH%.*} : '${PATH%.*} 

実行結果

$ /bin/sh /tmp/test/tt.sh
実行スクリプト ファイルパス :  /tmp/test
実行スクリプト ファイル名   :  tt.sh

PATH=home/to/path/file.ext

$ {PATH#*/} : to/path/file.ext
$ {PATH##*/}: file.ext
$ {PATH%/*} : home/to/path
$ {PATH%%/*}: home
$ {PATH%.*} : home/to/path/file

2013年5月29日水曜日

Mysql チューニング術

クエリキャッシュ

MySQL4.0.1から利用可能。
my.cnfに以下設定を記述する。
query_cache_type=1

値は、以下の通り。 0|クエリキャッシュを行わない 1|SELECT SQL_NO_CACHE ... クエリ以外をキャッシュする 2|SELECT SQL_CACHE ... クエリのみキャッシュする クエリキャッシュはスレッド内から設定する事も出来る。
SET GLOBAL QUERY_CACHE_TYPE=1;
SET SESSION QUERY_CACHE_TYPE=1;

MySQLは、クエリのハッシュをキーにしてキャッシュを管理するため、クエリの細かい違いに左右される。
以下の2つのクエリは異なるクエリと判断される。
SELECT * FROM table;
select * from table;

また、MySQLは先頭と末尾の余計な空白も取り除かない事に注意する必要がある。
MySQL4.0ではクエリキャッシュの対象を、先頭3文字が大小文字区別なしでSELに等しいかで区別する。これは、先頭がコメントで始まるクエリを全てキャッシュしない事につながる。

構文解析と分析と最適化

MySQLはキャッシュに無いクエリに対して、クエリ構文を解析して構成要素に分解する。
  • クエリ種類の判定(SELECT,INSERT,UPDATE,DELETE,SET,GRANT,...)
  • どのテーブルが関係するのか、エイリアスを使用するのか
  • WHERE句はどうなっているか
  • ヒントや修飾子を利用しているか
MySQLはクエリを基本的な要素に分解した後に、何を実行すべきかを判断する。ここからクエリオプティマイザが動き始める。クエリオプティマイザは、あらゆる情報を利用して、最も効率的なクエリの実行方法を見つけ出す。MySQLのボトルネックはほぼディスクI/Oであり、この負担を軽くすべく調査すべきレコード数を限定するために動く。
適切な判断を下すために、MySQLは以下の調査を行う。
  • 行を迅速に見つけるために、適切なインデックス候補が存在するか
  • どのインデックスが最適であるか、複数テーブルの場合それぞれについて
  • テーブルを結合する場合にどのテーブルがどのテーブルに依存するのか
  • テーブルにとってどの結合順序が適切か

EXPLAINによる調査

MySQLのSELECTクエリについて動作を調査するために、EXPLAINを利用する。
以下構成のテーブルに着いて、適当なレコードを1000000行挿入してある。
mysql@localhost> describe headline;
+------------+------------------+------+-----+-------------------+----------------+
| Field      | Type             | Null | Key | Default           | Extra          |
+------------+------------------+------+-----+-------------------+----------------+
| id         | int(10) unsigned | NO   | PRI |                   | auto_increment |
| headline   | varchar(255)     | NO   |     |                   |                |
| url        | varchar(255)     | NO   | UNI |                   |                |
| time       | int(10) unsigned | NO   |     | 0                 |                |
| expiretime | int(10) unsigned | NO   |     | 0                 |                |
| date       | varchar(6)       | NO   |     |                   |                |
| summary    | text             | YES  |     |                   |                |
| modtime    | timestamp        | YES  |     | CURRENT_TIMESTAMP |                |
+------------+------------------+------+-----+-------------------+----------------+
8 rows in set (0.45 sec)
プライマリキーを元にSELECTした結果。
mysql@localhost> select headline,url from headline where id=434 \G
*************************** 1. row ***************************
headline: headline::434
     url: http://www.example.com/news/434.html
1 row in set (0.08 sec)
上記クエリについてEXPLAINを実行。
mysql@localhost> explain select headline,url from headline where id=434 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: headline
         type: const
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 1
        Extra: 
1 row in set (0.43 sec)
MySQLは一致行数が1である事を知っている(primary keyは重複しない)ため、非常に高速に結果を得る事が出来る。
id
複数のテーブルを利用している場合、それぞれについて結果が返ってくる。idはその通し番号。
select_type
このテーブルがどの様な役割を果たすか。SIMPLE,PRIMARY,UNION,DEPENDENT UNION,SUBSELECT,DERIVED
table
MySQLがレコードを読み出すテーブル
type
どのような型の結合を使用するか。system,eq_ref,ref,range,index,ALL
possible_keys
テーブルから行を見つけ出すために使用出来るインデックスのリスト
key_len
キーのサイズ(バイト数)
ref
キーを照合する時に使用するカラムまたは値
rows
調査する必要があると推定された行数。
Extra
追加情報
範囲選択を実行してみる。
mysql@localhost> select url from headline where id between 10 and 13;
mysql@localhost> select url from headline where id between 1033 and 1043;
+---------------------------------------+
| url                                   |
+---------------------------------------+
| http://www.example.com/news/1033.html |
| http://www.example.com/news/1034.html |
| http://www.example.com/news/1035.html |
| http://www.example.com/news/1036.html |
| http://www.example.com/news/1037.html |
| http://www.example.com/news/1038.html |
| http://www.example.com/news/1039.html |
| http://www.example.com/news/1040.html |
| http://www.example.com/news/1041.html |
| http://www.example.com/news/1042.html |
| http://www.example.com/news/1043.html |
+---------------------------------------+
11 rows in set (0.47 sec)
mysql@localhost> explain select url from headline where id between 1033 and 1043 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: headline
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 12
        Extra: Using where
1 row in set (0.00 sec)
範囲選択を実行したため、typeがrangeになっている。また、refもNULLとなっている。rowsは推測値であるため、実施の結果に一致 しない場合もある。ExtraにUsing whereが追加されているが、これはWHERE句を利用して結果が絞り込まれた事を意味する。
インデックスがないカラムに基づいてレコードを取り出してみる。
mysql@localhost> select count(*) from headline where expiretime >= 4040;
+----------+
| count(*) |
+----------+
| 999615   |
+----------+
1 row in set (11.41 sec)
mysql@localhost> explain select count(*) from headline where expiretime >= 4040 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: headline
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1000000
        Extra: Using where
1 row in set (0.00 sec)
keyがNULLになり、possible_keysもNULLになっている。これは、キーを利用しない事を意味する。この種のクエリ実行が多い場合、インデックスを追加し、EXPLAINを実行してインデックスが利用される事を確認すればよい。
mysql@localhost> ALTER TABLE headline ADD INDEX (expiretime);
Query OK, 1000000 rows affected (4 min 51.75 sec)
Records: 1000000  Duplicates: 0  Warnings: 0
mysql@localhost> select count(*) from headline where expiretime >= 4040;
+----------+
| count(*) |
+----------+
| 999615   |
+----------+
1 row in set (2.24 sec)
mysql@localhost> explain select count(*) from headline where expiretime >= 4040 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: headline
         type: range
possible_keys: expiretime
          key: expiretime
      key_len: 4
          ref: NULL
         rows: 999683
        Extra: Using where; Using index
1 row in set (0.00 sec)
実行時間が短縮され、インデックスが利用されている事が確認出来る。また、ExtraにUsing indexとあるのは、インデックスの走査のみでデータが取得出来た事を意味する。
ORとINの違いについてみて見る。
mysql@localhost> select url from headline where id in (300,10000,8999);
+----------------------------------------+
| url                                    |
+----------------------------------------+
| http://www.example.com/news/300.html   |
| http://www.example.com/news/8999.html  |
| http://www.example.com/news/10000.html |
+----------------------------------------+
3 rows in set (0.39 sec)

mysql@localhost> explain select url from headline where id in (300,10000,8999) \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: headline
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 3
        Extra: Using where
1 row in set (0.00 sec)
mysql@localhost> select url from headline where id=300 OR id=10000 OR id=8999;
+----------------------------------------+
| url                                    |
+----------------------------------------+
| http://www.example.com/news/300.html   |
| http://www.example.com/news/8999.html  |
| http://www.example.com/news/10000.html |
+----------------------------------------+
3 rows in set (0.05 sec)

mysql@localhost> explain select url from headline where id=300 OR id=10000 OR id=8999 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: headline
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 3
        Extra: Using where
1 row in set (0.00 sec)
どちらも高速に実行出来ているし、EXPLAINの結果も変わらない。WHERE句で指定するidの候補数が増えた場合は、INを利用した方がクエリが短くなり構文解析時のオーバーヘッドが少なくなる。場合によってはINを利用する事が性能改善につながる。
サブクエリを利用した場合にどうなるかを見てみる。
mysql@localhost> select url from headline where id in (select max(id) from headline);
+------------------------------------------+
| url                                      |
+------------------------------------------+
| http://www.example.com/news/1000000.html |
+------------------------------------------+
1 row in set (4.15 sec)

mysql@localhost> explain select url from headline where id in (select max(id) from headline) \G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: headline
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1000000
        Extra: Using where
*************************** 2. row ***************************
           id: 2
  select_type: DEPENDENT SUBQUERY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Select tables optimized away
2 rows in set (0.00 sec)
インデックスを全く使用していないし、rowsを見ると全ての行を探そうとしている事が分かる。
INでなく=を利用したらどうなるか見てみる。
mysql@localhost> select url from headline where id = (select max(id) from headline);
+------------------------------------------+
| url                                      |
+------------------------------------------+
| http://www.example.com/news/1000000.html |
+------------------------------------------+
1 row in set (0.23 sec)
mysql@localhost> explain select url from headline where id = (select max(id) from headline) \G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: headline
         type: const
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 1
        Extra: 
*************************** 2. row ***************************
           id: 2
  select_type: SUBQUERY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Select tables optimized away
2 rows in set (0.00 sec)
プライマリキーを利用して1行だけ返すようになった。

結合

テーブル結合の際、MySQLは最も効率的であろう順序を推測する。このとき、各テーブルの相互関係を理解する必要がある。
select customer.name, order.date_placed, region.name
from customer, order, region
where order.customer_id = customer.id
and customer.region_id = region.id
and customer.name = 'John Doe';
上のクエリを実行した場合、MySQLはorderテーブルより先にcustomerテーブルを読む必要がある。つまり、customerテーブルのレコードを最初に読まなくてなならない。
MySQLにとって、最適な結合順序を見つけ出す事は苦手な技術の1つ。オプティマイザは単純に総当たり的に答えを見つける。場合によっては、結合順序の決定に時間がかかりすぎる事もある。

オプティマイザの機能と特徴

クエリをテストする場合、必ず現実的なデータを利用すべき。MySQLの問題に共通する原因は、あクエリオプティマイザがテストデータをどう扱うかにある。
一般に、MySQLはインデックスの利用によって『効率が向上する』と十分に確信出来る場合のみインデックスを利用する。これはテストを偽陰性(false negative)に導く事がある。

不十分な分散

データが多くても十分に分散していなければ、MySQLはインデックスを無視する事がある。例えば、全体の50%のレコードを読む必要がある場合、MySQLはテーブル全体をスキャンする方が高速だと判断する。この分岐点はおよそ30%。
このような挙動の理由は、ディスクシークの性能にある。MySQLは、 インデックスを利用した場合にインデックスのソート順でディスクアクセスを行う。つまり、現実のディスクをランダムにアクセスする可能性が高い。この問題 に対応するために、一定以上の割合のレコード読み出しが必要になった場合、より高速にデータを読み出せるであろう方法に切り替える。
もしも、テーブルのサイズを非常に小さいままで維持出来るとしたら、インデックスを使わない方がいい。
また、テストを行うのであれば、データサイズと分散度の両方について、現実的なデータを利用すべき出会う。

インデックスベースのソート

MySQLはソートに非常に時間がかかる。純粋に並べ替え作業にかかる時間は、高速なCPUを利用するしか対処方法は無い。問題は、ソートキーにインデックスを利用出来ない場合にある。MySQLではテーブル1つにつき、1つのインデックスしか利用出来ない。この場合、複数カラムからのインデックスを利用すればよい。
複数インデックスを利用する場合、インデックス指定の並びに意味がある。複数インデックスは、最も左に配置されたカラムのインデックスとして利用される。

あり得ないクエリ

MySQLは、すべてのクエリのWHERE句に対して、基本的な論理解析を実行し、無意味だと判断すれば0個のレコードを返す。これによって、無意味な実行時間が省略される。

LIKE句とフルテキストインデックス

LIKE句よりもフルテキストインデックスを利用した方が高速であるが、フルテキストインデックスを利用できる場合、MySQLはどれだけのレコードを読み取るかに関係なくフルテキストインデックスを利用しようとする点に注意する必要がある。

遅いクエリの特定

遅いクエリの発見は、その原因や対応に比べれば簡単。最も簡単な方法は、MySQLにクエリを処理させスロークエリログを出力させればよい。スロークエリログには多くの情報が入っているが、重要な遅い『理由』が書かれていない。
スロークエリログに記録されているクエリであっても、純粋にそのクエリが遅いとは断定出来ない。たまたまそのクエリが処理された時に、CPUやディスクなどの負荷が高かったのかもしれない。以下、その外部要因の一例。
  • テーブルロックの解除を待機していた
  • メモリ上にキャッシュされていなかった
  • バックアップなどが動いており、ディスクI/Oが大幅に遅くなっていた
  • 何百もの関係ないクエリを処理していたためCPUパワーが不足していた
これらの理由はまだ続く。そのため、1度スロークエリログに現れたとしても、それだけで判断する事は難しい。MySQLに付属するmysqldumpslowを利用してスロークエリログを要約し、遅いクエリがどれだけの頻度で実行されているかを調べる事が出来る。また、mytopを利用してリアルタイムで遅いクエリを監視する事も出来る。

MySQLに与えるヒント

多くのリレーショナルデータベースサーバでは、何らかのかたちでヒントの概念を実装している。ヒントとは、基礎となるSQLエンジンとクエリオプティマイザに追加情報を提供するための簡単な構文。
SELECT SQL_CACHE * FROM mytable ...
SELECT /*! SQL_CACHE */ * FROM mytable ...

結合順序

MySQLは通常、クエリで指定したテーブルの順序を無視する。そのかわり、それぞれのテーブルを調べて、どのような順序でテーブルを読むべきか判断する。検証は、EXPLAINで行う事が出来る。
クエリの順序を維持したい場合は、STRAIGHT_JOINヒントを利用すればよい。
SELECT * FROM table1 STRAIGHT_JOIN table2 WHERE ...

インデックスの使用

利用したいインデックスのリストを指示してそれ以外を無視させたい場合、USE INDEXを追加すればよい。逆に、無視させたい場合は、IGNORE INDEXを利用する。特定のインデックスを強制させたい場合は、FORCE INDEXを追加する。
SELECT * FROM mytable USE INDEX (mod_time, name) ...
SELECT * FROM mytable IGNORE INDEX (priority) ...
SELECT * FROM mytable FORCE INDEX (priority) ...

結果のサイズ

多数の行を扱う場合など、SQL_BUFFER_RESULTヒントを利用すると、MySQLは結果をバッファに格納するため、ロックを素早く解除出来る。
SQL_BIG_RESULTヒントは、多数の行を返す事をMySQLに伝える。これによって、MySQLはディスクベースの一時テーブルを利用する事に着いて積極的な判断を下すようになる。

クエリキャッシュ

SQL_QUERY_CACHEヒントを利用すれば、そのクエリをキャッシュするし、SQL_NO_CACHEヒントを利用すれば、キャッシュしない。

クエリの特殊なトリック

1つのクエリを2つに分解

MySQLが期待に反してクエリを最適化しない場合がある。例えば、WHERE句とORDER句で利用するインデックスが異なる場合、ファイルソートが必要になる事がある。これを2つのクエリに分解し、期待するインデックスを利用出来るようにするという回避策がある。
以下構文でサーバ上に一時変数を定義する事が出来る。
SELECT @sid := id FROM symbols WHERE symbol = 'ibm';
2つのクエリを実行することによるオーバーヘッドとソートによるオーバーヘッドとでは、一般にクエリ処理にかかる負荷の方が小さい。

ORの代わりにUNIONを使用

WHERE句で複数のカラムを指定した場合、場合によっては適切なインデックスが利用されずに完全なテーブルスキャンを実行する事がある。さらに、ORを利用した場合、MySQLは簡単に次の候補を選ぶ事が出来ない(MySQL5.0で修正される予定)。
この場合、UNIONを利用してクエリを書き換える事が出来る。
SELECT * FROM headline
WHERE expiretime <= 400 OR id <= 60000
ORDER BY expiretime ASC LIMIT 10;
(SELECT * FROM headline WHERE expiretime <= 400 ORDER BY expiretime ASC LIMIT 10)
UNION
(SELECT * FROM headline WHERE id <= 60000 ORDER BY expiretime ASC LIMIT 10)
ORDER BY expiretime ASC LIMIT 10 \G

2013年1月30日水曜日

「Office 2013」を2月7日から発売するとMicrosoftが発表

「Office 2013」を2月7日から発売するとMicrosoftが発表、パッケージは4種類


日本マイクロソフトが「次期Office」のパッケージ製品を2月7日から全国の販売店やオンラインストアで発売することを発表しました。


【次期 Office 最新情報 2013/1/15】 一般・個人向け次期 Office の日本市場向け発売日について - Office Blogs - Site Home - TechNet Blogs
http://blogs.technet.com/b/microsoft_office_/archive/2013/01/13/office-2013-1-15-office.aspx


発売されるパッケージは4種類。


Office Personal 2013(オフィス パーソナル 2013)は家庭向けで、Word、Excel、Outlookがセットになったもの。



Office Home&Business 2013(オフィス ホーム アンド ビジネス 2013)は家庭とビジネスの両方で使用する人向け。Word、Excel、Outlook、PowerPoint、OneNoteがセットになっています。



Office Professional 2013(オフィス プロフェッショナル 2013)は、Officeのあらゆる機能を使いたいという人向け。Word、Excel、Outlook、PowerPoint、OneNote、 Publisher、Accessがセットになっています。



Professionalと同じパッケージ内容で、学生や教職員向けには廉価なOffice Professional Academic 2013(オフィス プロフェッショナル アカデミック 2013)が提供されます。購入時には学校に在籍することを証明する書類の提示が必要です。


単体アプリケーションとしては
Word 2013
Excel 2013
Outlook 2013
PowerPoint 2013
OneNote 2013
Access 2013
Publisher 2013
Project 2013
Visio 2013
の9本となっています。

Office 2010、Office 2007、Office 2003を持っている人向けにはアップグレード優待パッケージも用意されています。エディションはアカデミック版やプロモーション製品、ダウンロード版を 含めてどれでもOKですが単体製品やボリュームライセンス版は対象外となっています。

数量限定 Office 2013 発売記念 | Microsoft atLife
http://www.microsoft.com/ja-jp/atlife/buy/article/office2013/launch/

2013年1月29日火曜日

Windows 8 Pro の優待5800円 (DL3300円) は月末まで、2月1日から2万5800円


Windows 8 発売時の大きなニュースは上位版の Windows 8 Pro でもアップグレード版がパッケージ 5800円、ダウンロード 3300円という破格の「発売記念優待価格」だったことですが、優待期間は予告どおり1月31日で終了してしまいます。

2月1日からの通常価格は、パッケージ版が一気に2万円上がる2万5800円。ダウンロード版も 2万5800円。駆け込み買いができるのもあと数日です。なお優待期間の終了後は、これつでプリインストールでしか提供されていなかった下位版 Windows 8 (無印) もラインナップに加わります。こちらは1万3800円。ただし Pro 相当にするためのアップグレードパッケージ Pro パックは1万2800円。エディション間の機能の違いや、DSP版についてはタグ: Windows 8 で過去記事の一覧をどうぞ。

2013年1月27日日曜日

XML-RPCによる投稿できるブログ一覧

※本投稿は quest大王 さんブロクの転載です。

 ●FC2
  ・エンドポイント=http://blog.fc2.com/xmlrpc.php
  ・ブログID=パスワード



 ●DTI
  ・エンドポイント=http://blog.dtiblog.com/xmlrpc.php
  ・ブログID=ログインID



 ●seesaa
  ・エンドポイント=http://blog.seesaa.jp/rpc
  ・ブログID=「マイブログ」内のブログ名を右クリックして出てくる「blog_ID=」の部分の数字



 ●JUGEMU
  ・エンドポイント=http://*****.jugem.jp/admin/xmlrpc.php
   *****の部分にはJugemKeyID
  ・ブログID=0



 ●269g
  ・エンドポイント=http://269g.jp/rpc
  ・ブログID=ログインID



 ●goo
  ・エンドポイント=http://blog.goo.ne.jp/xmlrpc.php
  ・ブログID=0
  ・パスワード=ブログライター使用設定が必要、その時のパスワードを使用



 ●プチモール
  ・エンドポイント=http://www.petitmall.jp/xmlrpc.php
  ・ブログID=0



 ●ヤプログ
  ・エンドポイント=http://www.yaplog.jp/xmlrpc
  ・ブログID=未入力



 ●忍者
  ・エンドポイント=http://samurai.blog.shinobi.jp/XMLRPC/
  ・ブログID=忍者ブログのURLの最初の「http://」と最後の「/」を除いたもの
  ・パスワード=設定した記事投稿用パスワード"



 ●PwBlog
  ・エンドポイント=http://www.pwblog.com/xmlrpc
  ・ブログID=「ブログURL+/rsd.xml」中の「api blogID="」以降の数字



 ●NetLaputa
  ・エンドポイント=http://blog.netlaputa.ne.jp/rpc/mt-xmlrpc.cgi
  ・ブログID=「マイブログ」中の「記事を投稿する」を右クリックしたプロパティの中の「blog_id=」以降の数字



 ●News-Handler
  ・エンドポイント=http://blog.nettribe.org/xmlrpc.php
  ・ブログID=0以上の数字



 ●ココログ
  ・エンドポイント=https://app.f.cocolog-nifty.com/t/api
  ・ブログID=「管理画面」中の「ブログ名」を右クリックしたプロパティの中の「blog_id=」以降の数字



 ●プチモール
  ・エンドポイント=http://www.petitmall.jp/xmlrpc.php
  ・ブログID=未入力



 ●ライブドア
  ・エンドポイント=http://cms.blog.livedoor.com/atom
  ・ブログID=投稿ページの「?blog_id=」以降の数字



 ●MT(ムーバブルタイプ)
  ・エンドポイント=http://ドメイン/mtディレクトリ/mt-xmlrpc.cgi
  ・ブログID=ブログ一覧画面で、ブログを右クリックした時のプロパティの中の「blog_id=」以降の数字



 ●WP(ワードプレス)
  ・エンドポイント=http://ドメイン/wpディレクトリ/xmlrpc.php
  ・ブログID=未入力



 ●wordpress.com
  ・エンドポイント=http://ユーザー名.wordpress.com/xmlrpc.php
  ・ブログID=未入力



 ●アセラ
  ・エンドポイント=http://a-thera.com/rpc
  ・ブログID=「マイブログ」中のブログ名を右クリックしたプロパティの中の「blog_id=」以降の数字
  ・ID・パスワード=XML-RPC API設定のID、パスワードを使用




■未検証分


 ●さくら
  ・エンドポイント=http://blog.sakura.ne.jp/rpc/
  ・ブログID=0
  ・ログインID=さくらのサブドメイン



 ●見て書いて
  ・エンドポイント=http://www.mitekaite.com/rpc/
  ・ブログID=



 ●VOX
  ・エンドポイント=http://www.vox.com/atom
  ・ブログID=



 ●So-net
  ・エンドポイント=http://blog.so-net.ne.jp/_rpc
  ・ブログID=未入力
  ・ID・パスワード=「AtomAPI/XML-RPC用ID」のID、パスワードを使用



 ●みぶろぐ
  ・エンドポイント=http://meblog.jp/rpc
  ・ブログID=



 ●アメーバ
  ・エンドポイント=http://atomblog.ameba.jp/servlet/_atom/blog
  ・ブログID=0



 ●teacup
  ・ブログURL=http://orange.ap.teacup.com/****/の場合
  エンドポイント=http://orange.ap.teacup.com/applet/****/postmsgrpc
  ・ブログID=管理画面の左上にある「AutoPage Master:」に続いて記載されているID(例:demo@8830)



 ●LOVELOG
  ・エンドポイント=http://blog.dion.ne.jp/atom
  ・エンドポイント=http://blog.dion.ne.jp/rpc
  ・ブログID=blog_id=xxx



 ●TypePad
  ・エンドポイント=http://www.typepad.jp/t/api
  ・エンドポイント=http://www.typepad.com/t/api
  ・ブログID=ブログのトップページのソースコードに、 <link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.typepad.jp/t/rsd/○○○" />と書いてある行があります。その○○○の数字が BlogID になります



 ●ブログ人
  ・エンドポイント=http://app.blog.ocn.ne.jp/t/api/
  ・ブログID=ブログのトップページのソースコードに、<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://app.blog.ocn.ne.jp/t/rsd/○○○" />と書いてある行があります。その○○○の数字が BlogID になります





■終わりに

今回、百数十のブログサービスを調査しました。その為、検証までの時間が間に合いませんでした。

まず、XML-RPC対応ブログの収集には 「mt-xmlrpc.cgi」「xmlrpc.php」「atom」「api」「rpc」等を、ブログサービスのURLに付加する方法と、ブログペット対応のブログサービスからの調査をしました。

まだまだ、調査の余地は残っていますが これだけの情報を収集・掲載しているサイトは他に無いと自負しています。


皆さんの調査・検証データがありましたら、是非、コメント・メール等でお知らせ下さい。
随時データを更新していきたいと思います。


今回の調査に辺り、ドリコムを始め アテナブログ等々既にサービスを終了したモノや終了予告が出ているところがありました。


吸収合併や、サイト売買が行われる中 こうしてひっそりと消えていくサービスがあることに ちょっと寂しさを感じました。


最後まで読んで頂き ありがとう m(_ _)m ございます!!
※本投稿は quest大王 さんブロクの転載です。

2011年11月20日日曜日

postgres テーブルの統計情報の表示

SELECT
st.relname,
n_tup_ins,
n_tup_upd,
n_tup_del,
pg_size_pretty(pg_relation_size(st.relid) + CASE WHEN cl.reltoastrelid = 0 THEN 0 ELSE pg_relation_size(cl.reltoastrelid) + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) FROM pg_index WHERE indrelid=cl.reltoastrelid)::int8, 0) END + COALESCE((SELECT SUM(pg_relation_size(indexrelid)) FROM pg_index WHERE indrelid=st.relid)::int8, 0)) AS size
FROM
pg_stat_all_tables st JOIN pg_class cl on cl.oid=st.relid
WHERE
schemaname = 'public'
ORDER BY
relname
-----------
pg_size_pretty(bigint)
 容量単位で目で見て理解できる形式にバイト数に領域を変換します。
pg_relation_size(oid)
 指定されたOIDを持つテーブルもしくはインデックスで使用されるディスク領域
pg_relation_size(text)
 指定された名前を持つテーブルもしくはインデックスで使用されるディスク領域。テーブル名はスキーマ名で条件付けられることもあります。

-----------
結果:
relname | n_tup_ins | n_tup_upd | n_tup_del | size
------------------------------+-----------+-----------+-----------+------------
news_tab | 37 | 47 | 43 | 128 kB
user_tab | 0 | 0 | 0 | 33 MB
order_tab | 2 | 6374426 | 0 | 2944 MB
(3 rows)

速いSQLを書くコツ!!

このページでは、SQLの実行速度を速くし、少ないメモリで実行するためのテクニックを紹介いたします。と言っても、実は『プログラマのためのSQL 第2版』の受け売りがほとんどでして、この本を読んでいただければ、ここを読む必要はありません。
 また、SQLの最適化の実行前と実行後で、SQL文の解析結果を比較することが重要です。適当にSQLをいじって速くなったからそれでよし、という非科学的な態度じゃダメですよ。SQLの解析方法については、別の文章で説明します(ただしオラクルのみ。僕がオラクルしか使ったことがないので)。
 なお、SQLの応答速度が遅い場合、その原因はSQL単体にあるとは限りません。索引の使用が不適切だったり、メモリの使用効率が悪かったり、ファイルI/Oが多くなっていたり、という他の原因も考えられます。

  1. サブクエリーを引数に取る場合、IN述語よりもEXISTS述語を使え
  2. 繰り返す。サブクエリーを引数に取る場合、IN述語を使うな
  3. IN述語の引数リストには、最もありそうなキーを左寄せしろ
  4. EXISTS述語のサブクエリー内では、SELECT * を使え
  5. 3つ以上のテーブルを結合させる時は冗長な結合条件を書け
  6. 行数を数えるときはCOUNT(*)よりもCOUNT(カラム名)を使え
  7. WHERE句の抽出条件は、最も制限の強いものから並べろ
  8. UNIONは使うな。UNION ALLを使え
  9. 実はインデックスが使用されていないという罠
  10. で、結局のところROWIDによるアクセスが最速なわけだが
  11. エディタにはEmacsを使え



  1. サブクエリーを引数に取る場合、IN述語よりもEXISTS述語を使え

     IN[NOT IN]とEXISTS[NOT EXISTS]は、たいていの場合、全く等しい結果集合を返します。しかし、この両者でサブクエリーを作る場合は、EXISTSの方が圧倒的に速い。例えば、有名人の誰かと同じ誕生日に生まれた社員を全て探すためのSQLを考えます。以下の2つのSQLは、同じ結果を返しますが、2番目の方が速いです。

     使用テーブル:
       Personnel(社員テーブル)
       Celebrities(有名人テーブル)

    1.INを使った場合(遅い)
    SELECT name
    FROM Personnel
    WHERE birthday IN (SELECT birthday
    FROM Celebrities);

    2.EXISTSを使った場合(速い)
    SELECT P.name
    FROM Personnel AS P
    WHERE EXISTS (SELECT
    FROM Clelebrities AS C
    WHERE P.birthday = C.birthday);

     なぜ、EXISTSの方が速いか?その理由は以下の2点です。

    もし結合キー(この場合はbirthday)にインデックスが張られていれば、Celebritiesテーブルの実表は見に行かず、インデックスのみを参照する。
    もしCelebritiesテーブルがインデックスを持っていなくても、優れたオプティマイザならば、birthday列をソートした一時テーブルを作り、2分探索することで、全表走査よりも効率的に検索を行なう。

  2. 繰り返す。サブクエリーを引数に取る場合、IN述語を使うな

     EXISTSで代用でき、しかもたいてい、その方が圧倒的に速いからです。
     INの引数にサブクエリーを取る場合、DBは、まずサブクエリーから実行し、その結果を一時的な作業テーブル上に格納します。つまりインライン・ビューを作るのです。その後に、その作業テーブルを全件走査します。これは、多くの場合、非常にコストがかかります。EXISTSを使えば、既に見たように、一時テーブルなど作成されません。
     ただし、ソースコードの可読性という点において、IN述語はEXISTS述語に勝ります。要するに、IN述語で書いた方がぱっと見て意味が分かりやすいコードになります。従って、IN述語を使っても十分短い応答時間が確保されているなら、そのSQL文を敢えてEXISTS述語で書き直す必要はありません。

  3. IN述語の引数リストには、最もありそうなキーを左寄せしろ

     なぜなら、INは、左から右へ引数を評価し、見つかった時点でtrueを返しそれより右の引数は見ないからです。以下の2つのSQLを比較してください。

    1.遅い(かもしれない)
    SELECT *
    FROM Address
    WHERE prefecture IN ('鳥取', '徳島', '東京', '大阪');

    2.速い(かもしれない)
    SELECT *
    FROM Address
    WHERE prefecture IN ('東京', '大阪', '鳥取', '徳島');


  4. EXISTS述語のサブクエリー内では、SELECT * を使え

     サブクエリーのSELECT句を書くには、以下の3つの選択肢があります。

    ①EXISTS (SELECT * FROM …)
    ②EXISTS (SELECT カラム名 FROM …)
    ③EXISTS (SELECT 定数 FROM …)

     このうち、最も良いのは①です。この書き方は、オプティマイザにどのカラムを使うべきかの選択を委ねることになります。そして、カラムにインデックスが張られていれば、実表を走査する必要はありません。
     ただし、例外的に②や③の方が①よりも高速な場合もあります。古いSQL製品の場合は②のように列名を指定した方が速いこともあります。また、Oracleその他の製品では、③のように「SELECT 1 FROM …」など、定数を指定すると高速になります。この書き方は、行へのポインタさえ得られれば、実際の行を読む必要がないことを、DBMSに指摘するからです。
     しかし、②は、もはや使う機会はないでしょうし、③の書き方は意味的な混乱を招くので、①を採用するべきです。

  5. 3つ以上のテーブルを結合させる時は冗長な結合条件を書け

    Table1:小さい
    Table2:大きい
    Table3:大きい

    上記のようなサイズの3つのテーブルがあるとします。共通のカラムで3つのテーブルを結合するとき、次のように書けます。

    SELECT *
    FROM Table1, Table2, Table3
    WHERE Table1.common = Table2.common
    AND Table1.common = Table3.common;

     あるいは、次のようにも書けます。しかし、こちらの方が遅くて非効率です。

    SELECT *
    FROM Table1, Table2, Table3
    WHERE Table2.common = Table3.common
    AND Table1.common = Table3.common;

     なぜなら、2番目のSQLは、最初にTable2とTable3という大きなテーブルを結合した大きな結果集合と、Table1とTable3を結合した小さな結果集合でマッチングを行なうからです。だから、結合条件は、小さなテーブルを最初に書くべきです。
     最も良い書き方は、テーブルのサイズが変わっても大丈夫なように、オプティマイザ自身にテーブルのサイズを決定させる書き方です。そのためには、次のように結合条件に冗長性を持たせます。

    SELECT *
    FROM Table1, Table2, Table3
    WHERE Table1.common = Table2.common
    AND Table2.common = Table3.common;
    AND Table3.common = Table1.common;

     もちろん、テーブルのサイズにあまり変化がない場合は、あえて結合条件に冗長性を持たせる必要はありません。

  6. 行数を数えるときはCOUNT(*)よりもCOUNT(カラム名)を使え

     このトリックは、インデックスを使います。したがって、これがうまく働くためには、COUNT関数の引数となるカラムにインデックスが張られている必要があります。例えば、

    SELECT COUNT(*)
    FROM Sales;

     よりは、次のSQLの方が速いかもしれない。

    SELECT COUNT(sale_id)
    FROM Sales;

     ここで、sale_idがSalesテーブルの主キーだとすれば、当然、sale_idにはユニークなインデックスが存在します。それを利用するのが、このトリックです。

  7. WHERE句の抽出条件は、最も制限の強いものから並べろ

     抽出条件がANDでつながっている場合は、制限の強いもの、つまりそれによって選択される行数が少ないものから順に並べる方が、効率がよいです。例えば、以下の通り。

    1.遅い
    SELECT *
    FROM Student
    WHERE sex = 'male'
    AND grade = 'A';

    2.速い
    SELECT *
    FROM Student
    WHERE grade = 'A'
    AND sex = 'male';

     なぜなら、評価がAの生徒の方が、男子学生よりも少ないから。この学校がハーレムのごとき場所なら話は別ですが。

  8. UNIONは使うな。UNION ALLを使え。

     UNIONは、二つの結果集合をマージします。しかし、重複行を排除するためのソート処理にコストがかかります。もし重複を気にしなくてよい場合なら、UNIONの代わりにUNION ALLを使ってください。そうすればソートは発生しません。

  9. 実はインデックスが使用されていないという罠。

     皆さんが検索するテーブルには、きっとインデックスが張られているでしょう。インデックスは、行数や列数の多い表を短時間で検索するためのテクニックとしては非常にポピュラーです。その原理は、C言語のポインタ配列と同じです。サイズの大きなオブジェクト配列を検索するよりも、サイズの小さなポインタ配列を検索した方が効率がいい、というわけです。しかも、2分探索による高速検索が可能なよう工夫されています。
     さて、Aという列にインデックスが張られているとします。以下のSQLはそのインデックスを使うつもりで、実のところテーブルXXを全件検索してしまっています。

    ①検索条件の左側で式を用いている
    SELECT A
    FROM XX
    WHERE A * 1.1 > 100

     検索条件の右側で式を用いれば、インデックスが使用されます。従って、代わりに
       WHERE A > 100/1.1
     という条件を使えばいいわけです。あるいは、関数索引を使うという方法もありますが、トリッキーなので推奨しません。

    ②NULLを指定している
    SELECT A
    FROM XX
    WHERE A IS NULL

     なぜなら、インデックスの中にはNULLは存在しないから。NULLは値ではないのです。

    ③否定形を用いている
    SELECT A
    FROM XX
    WHERE A <> 100

     否定形(NOT EQUAL, NOT IN)はインデックスを使用できません。

    ④ORを用いている
    SELECT A
    FROM XX
    WHERE A > 100 OR B = 'abc'

     理由は知らない。とにかくORを使うな。どうしても使いたいならビットマップ索引を張りましょう。

    ⑤LIKE述語を用いている
    SELECT A
    FROM XX
    WHERE A LIKE '%a'

     理由は知らない。とにかくLIKEを使うな。

  10. で、結局のところROWIDによるアクセスが最速なわけだが。

     もしあなたがROWIDの存在を知らなければ、今すぐに

    SELECT rowid
    FROM 適当なテーブル名;

     というSQLを実行してください。

    ROWID
    ------------------
    AAAF+OAAIAAABmMABI
    AAAF+OAAIAAABmMABK
    AAAF+OAAIAAABmMABL

     などといった列が選択されるはずです。 ROWIDはどのテーブルでも必ず持っている擬似列であり、そこに格納されている値はレコードの物理アドレスです。つまりROWIDはポインタの役割を果たす。インデックスもROWIDを使用しています。 ROWIDは、セッションが終了すると変化するかもしれませんが、ユーザセッション中は不変であり、Oracleでは常に最速のアクセスが保証されます。

  11. エディタにはEmacsを使え

     SQLに限った話ではないのですが、プログラムソースをコーディングするための最も効率のよいエディタは、現時点(2002年)では間違いなくEmacsです。反論は許されません。もともとUNIX上のエディタとして有名でしたが、最近ではWindows上でも動作します。
     Emacsを使ってSQLを効率よくコーディングするためには、以下の2つの機能を効果的に使う必要があります。

      1.sql-mode
      2.abbreviation(入力補完)

     sql-modeは、その名の通り、SQLをコーディングするための機能(Emacsの用語ではメジャーモード)です。予約語のハイライト(ANSI、Oracle、Postgresに対応)、や自動インデント、さらにSql*Plusのインターフェースとして使うことができます。とりわけ、このインターフェース機能は重要です。なぜなら、Sql*PlusがWindowsのエディタに劣らず貧弱だからです。コマンドの履歴はもてない、行編集をすることもできない、入力補完機能もない。editコマンドを使えばOSのエディタを呼び出せるものの、そこで呼び出されたエディタがメモ帳では焼け石に水と言うほかありません。またオラクル以外にもPostgres、MySQL、DB2、SQLServerなどのDBMSに対応しています。