PostgreSQL の実行計画の Tid Scan

PostgreSQL には ORACLE の ROWID のように 行を素早く指定するための列 ctid があります。

db=# SELECT ctid, * FROM test.table1;

   ctid   |   f1  |      f2
----------+-------+---------------
 (0,1)    | A143H | test@test.com
 (0,2)    | A393G | test@test.com
 (0,3)    | A380E | test@test.com
 (0,4)    | A147K | test@test.com

ctid は、行バージョンの物理的位置なので 行を更新したり、VACUUM FULL で変わってしまいます。

ただ、この ctid を使用するとかなり早く行を取得できます。 このときの実行計画に出てくる演算子が Tid Scan なのです。

実際に実行計画を取得してみます。

db=# EXPLAIN
db-# SELECT * FROM test.table1 WHERE ctid = '(0,2)';

                         QUERY PLAN
------------------------------------------------------------
Tid Scan on table1  (cost=0.00..4.01 rows=1 width=218)
  TID Cond: (ctid = '(0,2)'::tid)

Tid Scan と出ました。

PRIMARY KEY で検索した場合の実行計画も取得してみます。

db=# EXPLAIN
db-# SELECT * FROM test.table1 WHERE field1 = 1;

                                QUERY PLAN
---------------------------------------------------------------------------
 Index Scan using table1_pkey on table1  (cost=0.00..8.27 rows=1 width=50)
   Index Cond: ((field1)::text = '1'::text)

Index Scan よりも上の Tid Scan の方がコストが小さいですね。

psql でコマンドラインから変数に値を代入する

前回 psql の変数について書きましたが 変数への値の代入は psql を起動するコマンドラインからもできます。 というか、バッチ処理などを考えるとそっちがメインになると思います。 (ヒアドキュメントという手もありますが)

SQL は、前回と同じものを使用します。

SELECT * FROM generate_series(1, 100) 
WHERE generate_series between :start AND :end;

start と end という 2 つの変数を使用しています。

コマンドラインで指定するには、v オプションを使用します。

$ psql -f test.sql -v start=3 -v end=9 db

 generate_series
-----------------
               3
               4
               5
               6
               7
               8
               9
(7 rows)

特定の日付や期間で SQL を実行したい場合などに使えます。

psql で変数を扱う

ORACLE の sql*plus などと同じように psql でも変数を扱うことができます。

変数は set コマンドで値を代入します。

db=# \set value 2

上の例では、value という変数に 2 を入れました。

前回の echo コマンドで、値を出力できます。

db=# \echo :value
2

SQL の中で使用することもできます。

db=# SELECT :value;

 ?column?
----------
        2
(1 row)

変数を使って SQL の条件を設定することもできます。

db=# \set start 3
db=# \set end 10
db=# \echo :start - :end
3 - 10

変数を設定して、WHERE 句で使用します。

db=# SELECT * FROM generate_series(1, 100) 
db-# WHERE generate_series between :start AND :end;

 generate_series
-----------------
               3
               4
               5
               6
               7
               8
               9
              10
(8 rows)

意味の無い SQL ですが、3 から 10 にしぼれています。

コマンドの結果も変数に代入できますが、 文字列を扱う場合、エスケープがちょっとややこしいです。

db=# \set today ''''`date +"%Y/%m/%d"`''''
db=# select :today;

  ?column?
------------
2012/12/15

psql の出力コマンド

psql には \echo \qecho というコマンドがあります。

db=# \echo hello
hello

このように文字列を出力することができます。

またコマンドも実行できます。

db=# \echo `date +"%Y/%m/%d"`
2012/12/15

コマンドはバッククォートで囲みます。

db=# \echo `pwd`
/tmp

次のように psql を使用しているときに ログファイルに 色々と出力できるので便利です。

$ psql -f test.sql db > test.log

巳年だから Python ?

そのようなことをネットで読んで その周辺をウロウロしていたら Bottle という Python の Web フレームワークを紹介しているサイトがありました。

[参考サイト]
Pythonを始めるなら、1ファイルの軽量Webフレームワーク「Bottle」がおすすめ - モジログ

何の気なしに試してみると 30秒くらいで Web ページが表示されました。 仕組みはサッパリですが、とにかく動きました。

やり方は上記サイトに書いてありますが、こんな感じです。

  • 1ファイルをダウンロードして Python が入ってるサーバに置く
  • 同じフォルダに hello 出力用のスクリプトを置く(コピペ)
  • 上記スクリプトを起動する

とにかく試しに動かすところまでが早いのが良かったです。

謹賀新年 2013

あけましておめでとうございます。
初めての人も、そうで無い人も、 今年もよろしくお願いします。

WRITE_0663_01

全ての技術者とって 2013年が良い年になりますように!

Google サイト内検索

Amazonアソシエイト