SaaSサンプルデータ生成のまとめ
"Fighting Churn With Data: Science and strategy for keeping your customers"というSaaSデータの分析をまとめたCarl S. Goldさんの書籍のサンプルデータを生成するまでの流れをまとめたもの。下記のYouTubeにある動画でも解説されているが、私の理解が足りず、いくつか躓いた部分があったので、メモしておく。
リポジトリのクローン
まずは下記のリポジトリをダウンロードしてデスクトップにでもおいておく。
% git clone https://github.com/carl24k/fight-churn.git
PostgreSQLとPyCharmのインストール
- Python 3.9
pip3 install -r requirements.txt
でパッケージをインストール(リポジトリにおいてある)
- PyCharm
Community Edition
でOK
- PostgreSQL
スキーマの作成
次はスキーマーを作成する。まずはPyCharmを起動して、クローンしてきたfight-churn-master
をプロジェクトに指定して開く。スキーマーを作成するPythonファイルはchurndb.py
、データを生成するのはchurnsim.py
。
churndb.py
にはschema_name='socialnet7'
がデフォルトのスキーマー名として設定されている。変更する必要がなければ、このままにしておく。コンフィグレーションファイルの設定を行い、スクリプトパスは下記を設定する。
/Users/<name>/Desktop/fight-churn-master/fightchurn/datagen/churndb.py
コンフィグレーションファイルの設定でPostgreSQLへの接続設定をEnvironmentに記載する。
- CHURN_DB: churn
- CHURN_DB_USER: PostgreSQLに接続するユーザー名
- CHURN_DB_PASS: PostgreSQLに接続するユーザーのパスワード
- CHURN_OUT_DIR: ログを書き出すディレクトリ
これらの設定が終わったらchurndb.py
を実行する。実行完了後、PostgreSQLにchurn.socialnet7
という形でテーブルが複数作成されている。
シミュレーションデータの生成
次はテーブルにシミュレーションデータをインサートする。使用するファイルはchurnsim.py
。churnsim.py
のmain
関数のところで、シミュレーションする期間やユーザー数が指定できるが、ここもそのままでよければ変更しない。デフォルトの6ヶ月の設定でも、12GBくらいのデータが生成される。スペックにもよるが私のPCでは1時間程度かかった。シミュレーションの結果はsubscription
とevent
に挿入される。account
やevent_type
にもデータはインサートされる。
コンフィグレーションファイルの設定を行い、スクリプトパスは下記を設定する。
/Users/<name>/Desktop/fight-churn-master/fightchurn/datagen/churnsim.py
コンフィグレーションファイルの設定でPostgreSQLへの接続設定をEnvironmentに記載する。
- CHURN_DB: churn
- CHURN_DB_USER: PostgreSQLに接続するユーザー名
- CHURN_DB_PASS: PostgreSQLに接続するユーザーのパスワード
- CHURN_OUT_DIR: ログを書き出すディレクトリ
実行すると下記のログが出力される。
Creating 10000 initial customers for month of 2020-01-01 Simulated customer 0/10000: 4 subscriptions & 108 events Simulated customer 100/10000: 453 subscriptions & 132,390 events [略] [略] Simulated customer 1300/1331: 1,329 subscriptions & 383,867 events Created 1331 new customers for month 2020-05-01, now 55231 subscriptions Process finished with exit code 0
データがインサートされているか確認しておく。
% qsql -U postgres -d churn -W churn=# SELECT COUNT(1) FROM socialnet7.subscription; count ------- 55231 (1 row) churn=# SELECT * FROM socialnet7.subscription LIMIT 10; id | account_id | product | start_date | end_date | mrr | quantity | units | bill_period_months ----+------------+--------------+------------+------------+------+----------+-------+-------------------- 0 | 1 | 'socialnet7' | 2020-01-13 | 2020-02-13 | 9.99 | | | 1 1 | 1 | 'socialnet7' | 2020-02-13 | 2020-03-13 | 9.99 | | | 1 2 | 1 | 'socialnet7' | 2020-03-13 | 2020-04-13 | 9.99 | | | 1 3 | 1 | 'socialnet7' | 2020-04-13 | 2020-05-13 | 9.99 | | | 1 4 | 2 | 'socialnet7' | 2020-01-04 | 2020-02-04 | 9.99 | | | 1 5 | 2 | 'socialnet7' | 2020-02-04 | 2020-03-04 | 9.99 | | | 1 6 | 2 | 'socialnet7' | 2020-03-04 | 2020-04-04 | 9.99 | | | 1 7 | 2 | 'socialnet7' | 2020-04-04 | 2020-05-04 | 9.99 | | | 1 8 | 2 | 'socialnet7' | 2020-05-04 | 2020-06-04 | 9.99 | | | 1 9 | 3 | 'socialnet7' | 2020-01-10 | 2020-02-10 | 9.99 | | | 1 (10 rows) churn=# SELECT COUNT(1) FROM socialnet7.event; count ---------- 16995997 (1 row) churn=# SELECT * FROM socialnet7.event LIMIT 10; account_id | event_time | event_type_id ------------+---------------------+--------------- 1 | 2020-01-14 20:03:13 | 4 1 | 2020-01-15 04:42:10 | 4 1 | 2020-01-16 11:57:11 | 0 1 | 2020-01-17 07:16:53 | 0 1 | 2020-01-17 00:23:51 | 4 1 | 2020-01-17 03:39:04 | 4 1 | 2020-01-20 23:59:07 | 4 1 | 2020-01-22 16:20:53 | 2 1 | 2020-01-23 03:04:57 | 2 1 | 2020-01-25 02:40:13 | 2 (10 rows) churn=# SELECT * FROM socialnet7.event_type; event_type_id | event_type_name ---------------+----------------- 0 | post 1 | newfriend 2 | like 3 | adview 4 | dislike 5 | unfriend 6 | message 7 | reply (8 rows) churn=# SELECT COUNT(1) FROM socialnet7.account; count ------- 14641 (1 row) churn=# SELECT * FROM socialnet7.account LIMIT 10; id | channel | date_of_birth | country ----+-----------+---------------+--------- 1 | appstore1 | 2002-12-05 | US 2 | appstore2 | 1971-07-24 | NZ 3 | appstore2 | 1949-02-17 | GB 4 | appstore1 | 1987-09-23 | NZ 5 | appstore1 | 1972-07-11 | CA 6 | appstore2 | 1976-10-25 | IN 7 | appstore2 | 1994-04-19 | SE 8 | web | 1958-05-16 | CN 9 | web | 1976-03-10 | AR 10 | appstore2 | 1973-11-26 | CA (10 rows)
下記のER図は私が勝手に作ったもの。多分こんな感じだと思われる。そして、dbdiagramすごく便利。
別のサーバに移動する必要があったので、ダンプファイルを作成して、インポート。
[PC1] % pg_dump churn > ~/Desktop/churndump [PC2] $ psql -U aki -d postgres -W >> OSのスーパユーザーのパスワードが必要 postgres=> CREATE DATABASE churn postgres=> quit $ psql churn < ~/Desktop/churndump >> OSのスーパユーザーのパスワードが必要 # workerにデータベースとテーブル権限を付与 # もっと効率的かつセキュアにやれるっぽいが、ここらへんの理解が足りてない。 $ \c churn >> OSのスーパユーザーのパスワードが必要 churn=# GRANT ALL PRIVILEGES ON DATABASE churn TO worker; churn=# GRANT ALL ON TABLE socialnet7.account TO worker; churn=# GRANT ALL ON TABLE socialnet7.active_period TO worker; churn=# GRANT ALL ON TABLE socialnet7.active_week TO worker; churn=# GRANT ALL ON TABLE socialnet7.event TO worker; churn=# GRANT ALL ON TABLE socialnet7.event_type TO worker; churn=# GRANT ALL ON TABLE socialnet7.metric TO worker; churn=# GRANT ALL ON TABLE socialnet7.metric_name TO worker; churn=# GRANT ALL ON TABLE socialnet7.observation TO worker; churn=# GRANT ALL ON TABLE socialnet7.subscription TO worker;
以上でおわり。