♾️

Superset入門

に公開

はじめに

モダンデータスタックを構成するツール群を勉強しているのですが、折角、データ連携しても、「で、どうすんの?」が必要かなと思いました。といっても、いわゆる BI ツールはお高いので、お高くないもので探したところ、ありました。(笑)

https://superset.apache.org/

ということで、やってみましょう。

やってみる

方針

開発用には、docker-compose を、実運用には、Kubernetes を進めているようで、実際、docker-compose であれば簡単に動きます。
ただ、「本番では、docker-compose するな」と何度も書いてあり、また、「お高くないもの」もテーマなので、仮想環境ではなく、実環境にインストールしてみることにします。

環境

今回は、以下の EC2 環境に導入することにします。

項目 備考
インスタンスタイプ t3a.large USD 0.0979 / 時間 @東京
ボリュームタイプ gp3 USD 0.096/GB 月 @東京
ボリュームサイズ 8 GiB USD 0.768 / 月 @東京
OS Amazon Linux 2023 Amazon Linux 2023.7.20250331

これを平日の 10:00-20:00 の稼働にすると、月額20ドル強という感じです。(QuickSight だと1ユーザー分ぐらいでしょうか)

事前導入(Superset 以外)

https://superset.apache.org/docs/installation/pypi

git

構成管理に git を導入します。

$ sudo dnf install git
:
Installed:
  git-2.47.1-1.amzn2023.0.2.x86_64
  git-core-2.47.1-1.amzn2023.0.2.x86_64
  git-core-doc-2.47.1-1.amzn2023.0.2.noarch
  perl-Error-1:0.17029-5.amzn2023.0.2.noarch
  perl-File-Find-1.37-477.amzn2023.0.6.noarch
  perl-Git-2.47.1-1.amzn2023.0.2.noarch
  perl-TermReadKey-2.38-9.amzn2023.0.2.x86_64
  perl-lib-0.65-477.amzn2023.0.6.x86_64

Complete!

$ git --version
git version 2.47.1

PostgreSQL

Superset のメタデータデータベースは、PostgreSQL か MySSQL なので、PostgreSQL を導入します。あとで、サンプルデータベースとしても使います。
(devel を入れておかないと、後で、psycopg2 の導入で失敗するので入れておきましょう)

$ sudo dnf install postgresql17 postgresql17-server postgresql17-server-devel
:
Installed:
  clang-15.0.7-3.amzn2023.0.2.x86_64
  clang-devel-15.0.7-3.amzn2023.0.2.x86_64
  clang-libs-15.0.7-3.amzn2023.0.2.x86_64
  clang-resource-filesystem-15.0.7-3.amzn2023.0.2.x86_64
  clang-tools-extra-15.0.7-3.amzn2023.0.2.x86_64
  cmake-filesystem-3.22.2-1.amzn2023.0.4.x86_64
  compiler-rt-15.0.7-3.amzn2023.0.1.x86_64
  cpp14-14.2.1-7.amzn2023.0.1.x86_64
  emacs-filesystem-1:28.2-3.amzn2023.0.10.noarch
  gc-8.0.4-5.amzn2023.0.2.x86_64
  gcc14-14.2.1-7.amzn2023.0.1.x86_64
  gcc14-c++-14.2.1-7.amzn2023.0.1.x86_64
  gcc14-libstdc++-devel-14.2.1-7.amzn2023.0.1.x86_64
  glibc-devel-2.34-117.amzn2023.0.1.x86_64
  glibc-headers-x86-2.34-117.amzn2023.0.1.noarch
  guile22-2.2.7-2.amzn2023.0.3.x86_64
  kernel-headers-6.12.20-23.97.amzn2023.x86_64
  keyutils-libs-devel-1.6.3-1.amzn2023.0.2.x86_64
  krb5-devel-1.21.3-1.amzn2023.0.1.x86_64
  libatomic-14.2.1-7.amzn2023.0.1.x86_64
  libcom_err-devel-1.46.5-2.amzn2023.0.2.x86_64
  libedit-devel-3.1-38.20210714cvs.amzn2023.0.2.x86_64
  libicu-67.1-7.amzn2023.0.3.x86_64
  libicu-devel-67.1-7.amzn2023.0.3.x86_64
  libkadm5-1.21.3-1.amzn2023.0.1.x86_64
  libmpc-1.2.1-2.amzn2023.0.2.x86_64
  libomp-15.0.7-5.amzn2023.0.1.x86_64
  libomp-devel-15.0.7-5.amzn2023.0.1.x86_64
  libselinux-devel-3.4-5.amzn2023.0.2.x86_64
  libsepol-devel-3.4-3.amzn2023.0.3.x86_64
  libtool-ltdl-2.4.7-1.amzn2023.0.3.x86_64
  libverto-devel-0.3.2-1.amzn2023.0.2.x86_64
  libxcrypt-devel-4.4.33-7.amzn2023.x86_64
  llvm-15.0.7-3.amzn2023.0.1.x86_64
  llvm-devel-15.0.7-3.amzn2023.0.1.x86_64
  llvm-libs-15.0.7-3.amzn2023.0.1.x86_64
  llvm-static-15.0.7-3.amzn2023.0.1.x86_64
  llvm-test-15.0.7-3.amzn2023.0.1.x86_64
  make-1:4.3-5.amzn2023.0.2.x86_64
  ncurses-c++-libs-6.2-4.20200222.amzn2023.0.6.x86_64
  ncurses-devel-6.2-4.20200222.amzn2023.0.6.x86_64
  openssl-devel-1:3.2.2-1.amzn2023.0.1.x86_64
  pcre2-devel-10.40-1.amzn2023.0.3.x86_64
  pcre2-utf16-10.40-1.amzn2023.0.3.x86_64
  pcre2-utf32-10.40-1.amzn2023.0.3.x86_64
  postgresql17-17.4-1.amzn2023.0.1.x86_64
  postgresql17-private-devel-17.4-1.amzn2023.0.1.x86_64
  postgresql17-private-libs-17.4-1.amzn2023.0.1.x86_64
  postgresql17-server-17.4-1.amzn2023.0.1.x86_64
  postgresql17-server-devel-17.4-1.amzn2023.0.1.x86_64

Complete!

$ sudo postgresql-setup --initdb
 * Initializing database in '/var/lib/pgsql/data'
 * Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log

$ sudo systemctl enable postgresql
Created symlink /etc/systemd/system/multi-user.target.wants/postgresql.service → /usr/lib/systemd/system/postgresql.service.

$ sudo systemctl start postgresql
$ sudo systemctl status postgresql
● postgresql.service - PostgreSQL database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: disabled)
     Active: active (running) since Sun 2025-04-13 05:07:53 UTC; 15s ago
    Process: 34117 ExecStartPre=/usr/libexec/postgresql-check-db-dir postgresql (code=exited, sta>
   Main PID: 34119 (postgres)
      Tasks: 7 (limit: 9372)
     Memory: 17.5M
        CPU: 64ms
     CGroup: /system.slice/postgresql.service
             ├─34119 /usr/bin/postgres -D /var/lib/pgsql/data
             ├─34120 "postgres: logger "
             ├─34121 "postgres: checkpointer "
             ├─34122 "postgres: background writer "
             ├─34124 "postgres: walwriter "
             ├─34125 "postgres: autovacuum launcher "
             └─34126 "postgres: logical replication launcher "

Superset 用にデータベースとユーザーを作成します。

$ sudo -u postgres psql
psql (17.4)
Type "help" for help.

postgres=# create database superset owner postgres;
CREATE DATABASE
postgres=# create user superset with password 'superset';
CREATE ROLE
postgres=# grant all privileges on database superset to superset;
GRANT
postgres=# \c superset postgres
You are now connected to database "superset" as user "postgres".
postgres=# grant all privileges on schema public to superset;
GRANT
postgres=# grant all privileges on all tables in schema public to superset;
GRANT
postgres=# grant all privileges on all sequences in schema public to superset;
GRANT
postgres=# \q

Superset を OS のユーザーでなく、PostgreSQL のユーザーで接続するので、設定変更します。

/var/lib/pgsql/data/pg_hba.conf
115c115
< host    all             all             127.0.0.1/32            ident
---
> host    all             all             127.0.0.1/32            password

Redis

Superset のキャッシュと非同期実行用に Redis を導入します。

$ sudo dnf install redis6
:
Installed:
  redis6-6.2.14-2.amzn2023.0.2.x86_64

Complete!

$ sudo systemctl enable redis6
Created symlink /etc/systemd/system/multi-user.target.wants/redis6.service → /usr/lib/systemd/system/redis6.service.

$ sudo systemctl start redis6
$ sudo systemctl status redis6
● redis6.service - Redis persistent key-value database
     Loaded: loaded (/usr/lib/systemd/system/redis6.service; enabled; preset: disabled)
    Drop-In: /etc/systemd/system/redis6.service.d
             └─limit.conf
     Active: active (running) since Sun 2025-04-13 05:23:49 UTC; 8s ago
   Main PID: 37269 (redis6-server)
     Status: "Ready to accept connections"
      Tasks: 5 (limit: 9372)
     Memory: 2.3M
        CPU: 28ms
     CGroup: /system.slice/redis6.service
             └─37269 "/usr/bin/redis6-server 127.0.0.1:6379"

その他

後で叱られるものを予め入れておきます。(numpy のインストールでエラーになります)

$ sudo dnf install gcc gcc-c++ libffi-devel
:
Installed:
  annobin-docs-12.69-1.amzn2023.0.1.noarch
  annobin-plugin-gcc-12.69-1.amzn2023.0.1.x86_64
  cpp-11.5.0-5.amzn2023.0.3.x86_64
  gcc-11.5.0-5.amzn2023.0.3.x86_64
  gcc-c++-11.5.0-5.amzn2023.0.3.x86_64
  gcc-plugin-annobin-11.5.0-5.amzn2023.0.3.x86_64
  libffi-devel-3.4.4-1.amzn2023.0.1.x86_64
  libstdc++-devel-11.5.0-5.amzn2023.0.3.x86_64

Complete!

uv

最近、取り憑かれたように使ている uv を入れておきます。pip ではなく uv でやります。

$ curl -LsSf https://astral.sh/uv/install.sh | sh
downloading uv 0.6.14 x86_64-unknown-linux-gnu
no checksums to verify
installing to /home/ec2-user/.local/bin
  uv
  uvx
everything's installed!

Python

Superset のサポート範囲が 3.11 までなので、3.11 をインストールします(numpy が)

$ uv python install 3.11
Installed Python 3.11.12 in 2.88s
 + cpython-3.11.12-linux-x86_64-gnu

Superset の導入

uv プロジェクトの仮想環境に導入します。
Superset には、4種類のコンポーネントが存在しますが、まずは、必須の2つから。

  1. Superset アプリケーション自体
  2. メタデータ データベース
  3. キャッシュ レイヤー (オプションですが、一部の機能には必要です)
  4. ワーカーとビート (オプションですが、一部の機能には必要です)
$ uv init superset
Initialized project `superset` at `/home/ec2-user/superset`

$ cd superset
$ uv venv
Using CPython 3.11.12
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate

$ uv add apache-superset
Resolved 149 packages in 9.97s
      Built apache-superset==4.1.2
      Built func-timeout==4.3.5
      Built python-geohash==0.8.5
      Built wtforms-json==0.3.5
      Built pgsanity==0.2.9
      Built shortid==0.1.2
Prepared 145 packages in 32.27s
Installed 145 packages in 346ms
 + alembic==1.15.2
:
 + zstandard==0.23.0

環境変数と設定ファイル

SUPERSET_CONFIG_PATH 環境変数を上記のプロジェクトにします。

~/.bash_profile
# User specific environment and startup programs
export SUPERSET_CONFIG_PATH=~/superset/superset_config.py

上記の superset_config.py に DB の URL と SECRET_KEY を設定します。(まずは)

~/superset/superset_conig.py
SQLALCHEMY_DATABASE_URI="postgresql://superset:superset@localhost:5432/superset"
SECRET_KEY="yK7IX6WlirS/hez7DUjZvKLtS4/KAwJXrSYv4ZjX79whINlgFVD9ithQ"

LANGUAGES = {
    "ja": {"flag": "jp", "name": "Japanese"},
    "en": {"flag": "us", "name": "English"},
}

SECRET_KEY は、以下のように作成しておきましょう。

$ openssl rand -base64 42
yK7IX6WlirS/hez7DUjZvKLtS4/KAwJXrSYv4ZjX79whINlgFVD9ithQ

FLASK_APP 環境変数は、このプロジェクト用のものを ~/superset/.flaskenv に設定する。

~/superset/.flaskenv
FLASK_APP=superset

その他の Python パッケージ

後で叱られたり、ログにエラー出力されるものを入れておきます。

$ uv add pip setuptools
Resolved 151 packages in 141ms
Prepared 2 packages in 316ms
Installed 2 packages in 47ms
 + pip==25.0.1
 + setuptools==78.1.0

メタデータベースを PostgreSQL にするので、psycopg2 を入れます。

$ uv add psycopg2
Resolved 152 packages in 104ms
      Built psycopg2==2.9.10
Prepared 1 package in 12.78s
Installed 1 package in 2ms
 + psycopg2==2.9.10

メタデータベースを初期化して動かすまで

環境変数を反映する必要があるので、~/.bash_profile などで設定した場合は反映しておきましょう。PostgeSQL の設定変更も反映しておきます。

$ uv run superset db upgrade
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
:
Cleaning up slice uuid from dashboard position json.. Done.      
:
Revision ID: f7b6750b67e8
Revises: f84fde59123a
Create Date: 2024-05-09 19:19:46.630140
:

$ uv run superset fab create-admin
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
:
Username [admin]: 
User first name [admin]: 
User last name [user]: 
Email [admin@fab.org]: 
Password: 
Repeat for confirmation: 
Recognized Database Authentications.
Admin User admin created.

$ uv run superset init
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
:

$ uv run superset run -p 8088 --with-threads --reload --debugger
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
:
 * Serving Flask app 'superset'
 * Debug mode: off
2025-04-13 06:06:30,105:INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:8088
:
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
:

ここでローカルホストからはブラウザで接続可能になります。

gunicorn で動かす

上の方法で動かした際の警告に従って、WSGI server で動かします。

$ uv add gunicorn
Resolved 155 packages in 443ms
Audited 151 packages in 0.09ms

$ uv run gunicorn -w 2 --timeout 60 -b 0.0.0.0:8088 "superset.app:create_app()"
[2025-04-13 06:17:29 +0000] [46977] [INFO] Starting gunicorn 23.0.0
[2025-04-13 06:17:29 +0000] [46977] [INFO] Listening at: http://0.0.0.0:8088 (46977)
[2025-04-13 06:17:29 +0000] [46977] [INFO] Using worker: sync
[2025-04-13 06:17:29 +0000] [46978] [INFO] Booting worker with pid: 46978
[2025-04-13 06:17:29 +0000] [46979] [INFO] Booting worker with pid: 46979
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
2025-04-13 06:17:32,338:INFO:superset.initialization:Setting database isolation level to READ COMMITTED
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
2025-04-13 06:17:32,380:INFO:superset.initialization:Setting database isolation level to READ COMMITTED
2025-04-13 06:17:32,775:INFO:superset.utils.screenshots:No PIL installation found
2025-04-13 06:17:32,775:INFO:superset.utils.screenshots:No PIL installation found
2025-04-13 06:17:33,579:INFO:superset.utils.pdf:No PIL installation found
2025-04-13 06:17:33,600:INFO:superset.utils.pdf:No PIL installation found

これで、他のホストからも接続可能になります。

キャッシュ

https://superset.apache.org/docs/configuration/cache

$ uv add redis
Resolved 152 packages in 501ms
Audited 148 packages in 0.08ms

キャッシュの設定は、以下の4種類あります。

  • ダッシュボードフィルターの状態(必須): FILTER_STATE_CACHE_CONFIG
  • Explore チャートフォームデータ(必須): EXPLORE_FORM_DATA_CACHE_CONFIG
  • メタデータキャッシュ(オプション): CACHE_CONFIG
  • データセットからクエリされたチャートデータ(オプション): DATA_CACHE_CONFIG
superset/config.py
# ---------------------------------------------------
# Cache configuration
# ---------------------------------------------------
# Default cache timeout, applies to all cache backends unless specifically overridden in
# each cache config.
CACHE_DEFAULT_TIMEOUT = int(timedelta(days=1).total_seconds())

# Default cache for Superset objects
CACHE_CONFIG: CacheConfig = {"CACHE_TYPE": "NullCache"}

# Cache for datasource metadata and query results
DATA_CACHE_CONFIG: CacheConfig = {"CACHE_TYPE": "NullCache"}

# Cache for dashboard filter state. `CACHE_TYPE` defaults to `SupersetMetastoreCache`
# that stores the values in the key-value table in the Superset metastore, as it's
# required for Superset to operate correctly, but can be replaced by any
# `Flask-Caching` backend.
FILTER_STATE_CACHE_CONFIG: CacheConfig = {
    "CACHE_TYPE": "SupersetMetastoreCache",
    "CACHE_DEFAULT_TIMEOUT": int(timedelta(days=90).total_seconds()),
    # Should the timeout be reset when retrieving a cached value?
    "REFRESH_TIMEOUT_ON_RETRIEVAL": True,
    # The following parameter only applies to `MetastoreCache`:
    # How should entries be serialized/deserialized?
    "CODEC": JsonKeyValueCodec(),
}

# Cache for explore form data state. `CACHE_TYPE` defaults to `SupersetMetastoreCache`
# that stores the values in the key-value table in the Superset metastore, as it's
# required for Superset to operate correctly, but can be replaced by any
# `Flask-Caching` backend.
EXPLORE_FORM_DATA_CACHE_CONFIG: CacheConfig = {
    "CACHE_TYPE": "SupersetMetastoreCache",
    "CACHE_DEFAULT_TIMEOUT": int(timedelta(days=7).total_seconds()),
    # Should the timeout be reset when retrieving a cached value?
    "REFRESH_TIMEOUT_ON_RETRIEVAL": True,
    # The following parameter only applies to `MetastoreCache`:
    # How should entries be serialized/deserialized?
    "CODEC": JsonKeyValueCodec(),
}

まずは、おすすめのものだけ設定してみます。Superset の設定は、上記のように、config.py で指定されているものを上書きすることで反映させます。

~/superset/superset_config.py
FILTER_STATE_CACHE_CONFIG = {
    'CACHE_TYPE': 'RedisCache',
    'CACHE_DEFAULT_TIMEOUT': 86400,
    'CACHE_KEY_PREFIX': 'superset_filter_',
    'CACHE_REDIS_URL': 'redis://localhost:6379/0'
}

EXPLORE_FORM_DATA_CACHE_CONFIG = {
    'CACHE_TYPE': 'RedisCache',
    'CACHE_DEFAULT_TIMEOUT': 86400,
    'CACHE_KEY_PREFIX': 'superset_explore_',
    'CACHE_REDIS_URL': 'redis://localhost:6379/1'
}

非同期

https://superset.apache.org/docs/configuration/async-queries-celery

$ uv add celery flower
Resolved 155 packages in 708ms
Prepared 3 packages in 88ms
Installed 3 packages in 9ms
 + flower==2.0.1
 + prometheus-client==0.21.1
 + tornado==6.4.2

ドキュメントのとおりに設定してみます。ただし、REDIS_URL はキャッシュと重複しないようにします。

~/superset/superset_config.py
class CeleryConfig(object):
    broker_url = "redis://localhost:6379/2"
    imports = (
        "superset.sql_lab",
        "superset.tasks.scheduler",
    )
    result_backend = "redis://localhost:6379/2"
    worker_prefetch_multiplier = 10
    task_acks_late = True
    task_annotations = {
        "sql_lab.get_sql_results": {
            "rate_limit": "100/s",
        },
    }

CELERY_CONFIG = CeleryConfig
$ uv run celery --app=superset.tasks.celery_app:app worker --pool=prefork -O fair -c 4
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
2025-04-13 07:56:23,558:INFO:superset.initialization:Setting database isolation level to READ COMMITTED
2025-04-13 07:56:24,019:INFO:superset.utils.screenshots:No PIL installation found
2025-04-13 07:56:24,552:INFO:superset.utils.pdf:No PIL installation found
 
 -------------- celery@ip-10-48-152-157.ap-northeast-1.compute.internal v5.5.1 (immunity)
--- ***** ----- 
-- ******* ---- Linux-6.1.131-143.221.amzn2023.x86_64-x86_64-with-glibc2.34 2025-04-13 07:56:25
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         __main__:0x7ff2862b6bd0
- ** ---------- .> transport:   redis://localhost:6379/2
- ** ---------- .> results:     redis://localhost:6379/2
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery
                

チュートリアル

https://superset.apache.org/docs/using-superset/creating-your-first-dashboard

これをやるのに、examples データベースがあった方が良さそうなので、準備します。

examples

まずは、DB を準備します。

$ sudo -u postgres psql
psql (17.4)
Type "help" for help.

postgres=# create database examples owner postgres;
CREATE DATABASE
postgres=# grant all privileges on database examples to superset;
GRANT
postgres=# \c examples postgres
You are now connected to database "examples" as user "postgres".
examples=# grant all privileges on schema public to superset;
GRANT
examples=# grant all privileges on all tables in schema public to superset;
GRANT
examples=# grant all privileges on all sequences in schema public to superset;
GRANT
examples=# \q

設定を変更して、

superset_config.py
@@ -36,3 +36,5 @@
     }
 
 CELERY_CONFIG = CeleryConfig
+
+SQLALCHEMY_EXAMPLES_URI="postgresql://superset:superset@localhost:5432/examples"

投入します。

uv run superset load_examples
Loaded your LOCAL configuration at [/home/ec2-user/superset/superset_config.py]
:
Loading examples metadata and related data into examples
Creating default CSS templates
Loading [World Bank's Health Nutrition and Population Stats]
Creating table [wb_health_population] reference
Creating a World's Health Bank dashboard
Loading [Birth names]
Done loading table!
:

Sign-in から言語設定

ここまでセットアップしたサーバーにブラウザから接続します。

admin ユーザーと上記で指定したパスワードで Sign-in します。日本語メニューが嬉しい方は、言語設定ができますが、一部、翻訳漏れでエラーになる箇所もあります。

データベース接続

ここからは、本家のチュートリアルの補足です。
データベースへの接続は、右上の 設定 > データ > データベース接続 から開きます。examples を選択して編集へ進むと内容が確認できます。

テーブル

テーブルは、上段の データセット を選択することで一覧表示されます。チュートリアルで扱っている cleaned_sales_data で編集ボタンを押します。

チュートリアルでは、列、指標、計算列 の順に見ています。

Explore

テーブルの一覧からテーブル名をクリックすると Explore の画面に遷移します。チュートリアルに似たグラフを作った画面イメージです。裏の カスタマイズスタックスタイルスタック に変更してあります。

おわりに

いかがでしたでしょうか。
チュートリアルにない SQL Lab も使いやすそうですし、メール通知や Slack通知では、ヘッドレスブラウザを使用したダッシュボードイメージの送信もできるようなので、BI の画面の要らない人には、そういった共有もありかもしれませんね。

GitHubで編集を提案
株式会社ROBONの技術ブログ

Discussion