PostgreSQL で インデックス・オンリー・スキャン

PostgreSQL でも 9.2 から インデックス・オンリー・スキャンが使えるようになっています。

この機能は データを取得する際に、インデックスだけで事足りる場合は インデックスのみを使用するというものです。 Oracle では昔からありましたが PostgreSQL では 9.2 から実装されました。

通常は、検索にインデックスを使用しても、テーブルからデータを取得するために 別の領域(ヒープ)を読みに行くわけですが、これが不要になるためパフォーマンスの向上に かなり期待できる部分があります。

ただ、PostgreSQLは追記型のデータベースなので インデックスだけでは 古いデータかどうか判断できないため、インデックス・オンリー・スキャンの実装は 難しいとされていました。 これを 8.4 でバキュームのため?に追加された ビジビリティマップ というデータを使って「インデックスだけで大丈夫か」を判断しているそうです。

なので、インデックス・オンリー・スキャンといっても、場合によってはテーブルのデータを読みに行く必要があります。 更新が多いテーブルでは難しいかもしれません。

三焦経だけでもありがたいですし、ビジビリティマップが綺麗に?なるようにバキュームも重要です。

実行計画を見ると次のようになります。
( field1 がテーブルの主キー)

psql=# EXPLAIN
psql-# SELECT field1 FROM table1
psql-# WHERE field1 > 300000

Index Only Scan using table1_pkey on table1  (cost=0.43..
  Index Cond: (field1 > 300000)

Index Only Scan と出力されます。

コマンドプロンプトの FOR コマンドの出力をまとめる

FOR コマンドは処理を繰り返すことができます。

次のサンプルは、aaaa.txt の内容を行ごとに ダブルクォーテーションで囲んで出力しています。

C:\> FOR /F %I IN (aaaa.txt) DO @ECHO "%I" >> bbbb.txt

これは次のように書くことができます。

C:\> (FOR /F %I IN (aaaa.txt) DO @ECHO "%I") > bbbb.txt

こうすることで、ファイルを空にする処理が不要になったり 処理の速度が上がったりします。

Oracle のマルチテーブル・インサート

最近は PostgreSQL の機能も充実してきましたが Oracle にはまだまだ独自の機能が残っています。

今回は、前回やったマルチテーブル・インサートについて。

次のように INSERT文をまとめることができます。

SQL> INSERT ALL
  2    INTO table1 (field1, field2) VALUES ('xxxxx1', 'xxxxxxxxx')
  3    INTO table1 (field1, field2) VALUES ('xxxxx2', 'xxxxxxxxx')
  4    INTO table1 (field1, field2) VALUES ('xxxxx3', 'xxxxxxxxx')
  5  SELECT * FROM DUAL;

まとめるだけでなく複数のテーブルに INSERT できます。

SQL> INSERT ALL
  2    INTO table1 (field1, field2) VALUES ('xxxxx1', 'xxxxxxxxx')
  3    INTO table2 (field1, field2) VALUES ('xxxxx2', 'xxxxxxxxx')
  4    INTO table3 (field1, field2) VALUES ('xxxxx3', 'xxxxxxxxx')
  5  SELECT * FROM DUAL;

文末の DUAL に気づいたでしょうか?

  5  SELECT * FROM DUAL;

ここにはテーブルや福問い合わせを指定することができます。

つまり 次のようなことができてしまうわけです。

SQL> INSERT ALL
  2    INTO table1 (field1, field2) VALUES (fieldA, fieldB)
  3    INTO table2 (field1, field2) VALUES (fieldA, fieldC)
  4    INTO table3 (field1, field2) VALUES (fieldA, fieldD)
  5  SELECT * FROM table4;

さらに条件も指定することができます。

SQL> INSERT ALL
  2    WHEN fieldB < 10 THEN
  3      INTO table1 (field1, field2) VALUES (fieldA, fieldB)
  4    WHEN fieldC < 10 THEN
  5      INTO table2 (field1, field2) VALUES (fieldA, fieldC)
  6    WHEN fieldD < 10 THEN
  7      INTO table3 (field1, field2) VALUES (fieldA, fieldD)
  8  SELECT * FROM table4;

やっぱり Oracle は恐ろしいですね。

Oracle でも 1回の SQL で複数行 INSERT する

PostgreSQL や MySQL では次のように INSERT 文で 複数行を指定することができます。

psql=# INSERT INTO table1 (field1, field2)
psql-#   VALUES ('xxxxx1', 'xxxxxxxxx')
psql-#        , ('xxxxx2', 'xxxxxxxxx')
psql-#        , ('xxxxx3', 'xxxxxxxxx');

Oracle ではこの書き方ができません。

以下のように書きます。

SQL> INSERT ALL
  2    INTO table1 (field1, field2) VALUES ('xxxxx1', 'xxxxxxxxx')
  3    INTO table1 (field1, field2) VALUES ('xxxxx2', 'xxxxxxxxx')
  4    INTO table1 (field1, field2) VALUES ('xxxxx3', 'xxxxxxxxx')
  5  SELECT * FROM DUAL;

単に INSERT文をまとめただけのようですが この書き方は、異なるテーブルでもまとめることができます。 マルチテーブル・インサート と言うのですが 単に INSERT をまとめるだけではありません。

詳しくは次回。

コマンドプロンプトの DIR コマンドでファイルだけ出力する

コマンドプロンプトの DIR コマンドで ファイルだけを出力するときは 「/A」オプションで「ディレクトリ以外」を指定します。

C:\> DIR /A:-D

海外の顔文字みたいになってますが 「D」がディレクトリで、「-」が〇〇以外になります。

コロンは省略することができます。

C:\> DIR /A-D

「/B」オプションを付けてファイル名だけ、 なんてこともできます。

C:\> DIR /A:-D /B

Google サイト内検索

Amazonアソシエイト