LoginSignup
2
0

More than 3 years have passed since last update.

[Redash] Redshift で一時テーブルを利用していると、スキーマ情報を取得できない場合がある

Last updated at Posted at 2019-10-31

動作環境

現象

Redshift をデータソースに登録後、クエリを作成(または編集)するダッシュボードで、本来は左ペインに表示されるはずのスキーマ情報が表示されず、ページ右下に次のエラーメッセージが表示されることがあります。
※勿論いくら待ってもスキーマは表示されません。

schema_error.png

原因調査

Redash Scheduler のログを確認すると、次の Exception error が吐かれていました。

6d6321902c Failed refreshing schema for the data source: DS_Redshift
Traceback (most recent call last):
  File "/app/redash/tasks/queries.py", line 238, in refresh_schema
    ds.get_schema(refresh=True)
  File "/app/redash/models/__init__.py", line 157, in get_schema
    schema = sorted(query_runner.get_schema(get_stats=refresh), key=lambda t: t['name'])
  File "/app/redash/query_runner/__init__.py", line 134, in get_schema
    self._get_tables(schema_dict)
  File "/app/redash/query_runner/pg.py", line 289, in _get_tables
    self._get_definitions(schema, query)
  File "/app/redash/query_runner/pg.py", line 113, in _get_definitions
    raise Exception("Failed getting schema.")
Exception: Failed getting schema.

どうやらスキーマ情報を取得するスクリプト /app/redash/query_runner/pg.py で問題が発生しているようです。

そこで /app/redash/query_runner/pg.py の113行目辺りを確認すると、

/app/redash/query_runner/pg.py(109-113行目辺り)
    def _get_definitions(self, schema, query):
        results, error = self.run_query(query, None)

        if error is not None:
            raise Exception("Failed getting schema.")

単に引数で指定されたクエリを実行しているだけです。更にこのメソッドを呼び出している箇所を中心に調べてみると、次のクエリを渡していることが分かりました。

/app/redash/query_runner/pg.py(269-287行目辺り)
        query = """
        WITH tables AS (
            SELECT DISTINCT table_name,
                            table_schema,
                            column_name,
                            ordinal_position AS pos
            FROM svv_columns
            WHERE table_schema NOT IN ('pg_internal','pg_catalog','information_schema')
        )
        SELECT table_name, table_schema, column_name
        FROM tables
        WHERE
            HAS_SCHEMA_PRIVILEGE(table_schema, 'USAGE') AND
            (
                table_schema IN (SELECT schemaname FROM SVV_EXTERNAL_SCHEMAS) OR
                HAS_TABLE_PRIVILEGE('"' || table_schema || '"."' || table_name || '"', 'SELECT')
            )
        ORDER BY table_name, pos
        """

試しに手動で上記クエリを Redshift に投げると、次のエラーが発生しました。

ERROR:  schema "pg_temp_25" does not exist

ちなみに pg_temp_25 はタイミングによって pg_temp_8 だったり pg_temp_10 だったりしますが、要は pg_temp で始まる名前のスキーマが見つからない場合があるようです。

実はこの pg_temp で始まるスキーマは、CREATE TEMPORARY TABLE で一時テーブルを作成した際、同時に作成されるようです。
Redshift の仕様では、一時テーブルはセッションが切断された際に自動で削除されるようですが、一時スキーマは自動で削除されず、また手動で削除する術が用意されていないようです。(参考: https://qiita.com/kusanoiskuzuno/items/6e2b4103758cea7287bc)

尚、当社では Tableau からも Redshift を利用しており、そちらで作成された一時テーブルや一時スキーマが大量に存在していました。

対策

そもそも一時テーブルや一時スキーマを Redash で利用する必要がないので、スキーマ取得クエリに pg_temp から始まる一時スキーマを除外するよう変更を加えることにします。

今回は次のような Patch、Dockerfile を作成、ビルドし直すことで対応しました。

pg.py.patch
--- pg.py.org   2019-10-29 17:21:07.837000000 +0900
+++ pg.py   2019-10-29 17:21:41.357782805 +0900
@@ -274,6 +274,7 @@
                             ordinal_position AS pos
             FROM svv_columns
             WHERE table_schema NOT IN ('pg_internal','pg_catalog','information_schema')
+              AND table_schema NOT LIKE 'pg_temp_%'
         )
         SELECT table_name, table_schema, column_name
         FROM tables
Dockerfile
FROM redash/redash:7.0.0.b18042

ADD pg.py.patch /tmp/pg.py.patch

RUN patch -u /app/redash/query_runner/pg.py </tmp/pg.py.patch && \
    rm -f /tmp/pg.py.patch
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0