[Redash] Redshift で一時テーブルを利用していると、スキーマ情報を取得できない場合がある
動作環境
- Redash on Docker
- Redash version: redash/redash:7.0.0.b18042
現象
Redshift をデータソースに登録後、クエリを作成(または編集)するダッシュボードで、本来は左ペインに表示されるはずのスキーマ情報が表示されず、ページ右下に次のエラーメッセージが表示されることがあります。
※勿論いくら待ってもスキーマは表示されません。
原因調査
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行目辺りを確認すると、
def _get_definitions(self, schema, query):
results, error = self.run_query(query, None)
if error is not None:
raise Exception("Failed getting schema.")
単に引数で指定されたクエリを実行しているだけです。更にこのメソッドを呼び出している箇所を中心に調べてみると、次のクエリを渡していることが分かりました。
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.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
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
Author And Source
この問題について([Redash] Redshift で一時テーブルを利用していると、スキーマ情報を取得できない場合がある), 我々は、より多くの情報をここで見つけました https://qiita.com/nagase/items/34909fb1f6f1c134bf16著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .