Amazon Redshift: 検索パス(search_path)とSQL実行時のスキーマ名指定有無の関連性について

2015.05.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

超小ネタ&うっかりすると混乱を招く事もあるな〜と思い、備忘録としてこのエントリを書き出しておきます。Amazon Redshiftの『検索パス』にまつわるお話です。

検索パス(search_path)にまつわるお話

言いたい事はタイトルで言い切った感があるので、そこに至った経緯を。

Amazon Redshiftでは、『検索パス(search_path)』という設定項目があります。この情報は、Redshiftクラスタがスキーマを探す際にその内容と順番を定義しておくものとなります。

上記エントリでも言及しているように、新しくスキーマを作成した際はそのスキーマも定義しておかないと何かと不便ですよ、というのはまずあるかなと思います。

検索パス(search_path)の設定とスキーマ名の未指定で起こりうる問題

そして、今回遭遇したケースがここで紹介する内容となります。

パラメータグループ新規作成時、またデフォルトのパラメータグループについては、以下の様にスキーマが定義されており、

# show search_path;
  search_path                               
---------------
 $user, public
(1 row)

特に意識しなければ、新規にスキーマを作成した後は以下のようにpublicスキーマの後に新たにスキーマを追記しておくと思います。

# show search_path;
      search_path                               
---------------------------
 $user, public, cm_public
(1 row)

ですがここで、publicスキーマより前に別のスキーマ名が設定がされており、

# show search_path;
      search_path                               
---------------------------
 cm_public, $user, public
(1 row)

且つ、テーブル作成等でスキーマが指定されていないとどうなるでしょうか?

CREATE TABLE testtable (
  id INT NOT NULL,
  name VARCHAR(10) NOT NULL
);

実行者的にはスキーマ未指定=publicだと思っていても、以下の様にpublicスキーマでは無く、cm_publicスキーマにテーブルが作成されてしまうのです。

# SELECT COUNT(*) FROM public.testtable;
ERROR:  relation "public.testtable" does not exist
# SELECT COUNT(*) FROM testtable;
 count 
-------
     0
(1 行)
# \d testtable;
            テーブル "cm_public.testtable"
  列  |      型               |  修飾語  
------------------------------+--------------+----------
 id   | integer               | not null
 name | character varying(50) | not null

AWSの公式ドキュメントにも、以下のような記載があります。参照だけでなく、あらゆる場面でスキーマが未指定だった場合にこの情報を辿る訳ですね。

検索パスは search_path パラメータで定義します。このパラメータに、スキーマ名をカンマで区切ってリストします。検索パスは、オブジェクト(テーブルや関数など)がスキーマ修飾子なしの簡潔な名前で参照されたときにスキーマを検索する順序を指定します。

ターゲットスキーマを指定せずにオブジェクトを作成した場合は、検索パスにリストされている最初のスキーマにオブジェクトが追加されます。同じ名前の複数のオブジェクトが異なるスキーマ内に存在する場合、スキーマが指定されていないオブジェクト名は、その名前のオブジェクトを含む検索パス内の最初のスキーマを参照します。

勉強になりました!

まとめ

という訳でまとめ。

       r ‐、
       | ○ |        r‐‐、     良い子の諸君!
     _,;ト - イ、     ∧l☆│ ∧   
    (⌒`    ⌒ヽ   /,ト.-イ/,l  RedshiftにSQLアクセスする際は
    |ヽ  ~~⌒γ⌒) r'⌒`!´ `⌒) ちゃんとスキーマ名も付与しておこう。
    │ ヽー―'^ー-' (  ⌒γ⌒~~ /|  
    │  〉   | │ |`ー^ー―  r'|  search_pathの状況によっては
    │  /───────|  | |/ |  l  ト、|  意図しない結果を招く事もあるぞ。
   |  irー-、 ー ,}  |  /    i   
   | /   `X´ ヽ  /   入  |

追記:

半ば勢いで書いてしまいましたが、1つのクラスタで複数環境を整え(開発/検証/本番)、それらの環境間での利便性を考えて敢えてスキーマ名を指定しないケース、また『DDL系のものはスキーマ名を付けるけどそれ以外は...』というケースもある事を考えると、この辺りはトレードオフを考えて...というのもあるかも知れません。こういうケースもあるよ、という事でこのネタは心の片隅に置いといてもらえますと幸いです。