Tableauダッシュボードが壊れるたびに焦っていませんか?
Tableauのダッシュボード、会社で使っている人もいるかもしれませんね。時々、なんだか急に動かなくなったり、データが変になったりして慌てた経験がある人も少なくないようです。原因はいろいろ考えられるけど、作成自体に問題がなければ、大抵の場合はデータウェアハウス側で何か起きてる…そんなケースが多いみたいですね。
例えば、パイプラインの一部がうまく動かなかったとか、新しいテーブルと入れ替わってしまったとか、列名やカラムそのものがいつの間にか消えていたことも。あとはスキーマ自体が微妙に変わっちゃってたりすることもそこそこあります。他にも細かいパターンを挙げ出すときりがない感じ。
ただ、「これだ!」と原因を突き止めても、それだけじゃ実際どうすればいいか悩む場面も結構あるんですよね。
例えば、パイプラインの一部がうまく動かなかったとか、新しいテーブルと入れ替わってしまったとか、列名やカラムそのものがいつの間にか消えていたことも。あとはスキーマ自体が微妙に変わっちゃってたりすることもそこそこあります。他にも細かいパターンを挙げ出すときりがない感じ。
ただ、「これだ!」と原因を突き止めても、それだけじゃ実際どうすればいいか悩む場面も結構あるんですよね。
データウェアハウスが原因でダッシュボードが動かなくなる9つのシナリオ
なんとなく修正作業を始めるのって、案外すんなりいかないことが多い気がする。Tableauで何か問題が起きたとき、どれくらいの数のデータソースやダッシュボードに影響しているのか、いまいち掴みづらい場面もある。まあ、これ自体は難しいというよりは、やたら時間を持っていかれる印象が強い。でも全部手作業で一つずつチェックするのは、さすがに骨が折れるよね。
ところで、こういう状況になる前に、つまり誰かが不具合に気付く前から何となく予測できたりしないかな、と考えたことがある。実際には絶対じゃないけど、TableauのMetadata APIを使うことで、その可能性も出てきているようだ。このAPI自体はGraphQLっていう仕組みで動いていて、それなりに柔軟に欲しい情報だけ引っ張れるらしい。GraphQLについてもう少し知りたい場合は、「GraphQL . org」なんかも見てみると良さそう。
細かい話になるけど、この手法なら将来的には結構な工数削減にも繋がる可能性もありそう。ただし、全員にとって万能とは限らないので、その点は少し注意した方がいいと思う。それでも今まで七十回近く同じ作業を繰り返していた人には、一つの選択肢として検討する余地はありそうだな、と感じたりする。
ところで、こういう状況になる前に、つまり誰かが不具合に気付く前から何となく予測できたりしないかな、と考えたことがある。実際には絶対じゃないけど、TableauのMetadata APIを使うことで、その可能性も出てきているようだ。このAPI自体はGraphQLっていう仕組みで動いていて、それなりに柔軟に欲しい情報だけ引っ張れるらしい。GraphQLについてもう少し知りたい場合は、「GraphQL . org」なんかも見てみると良さそう。
細かい話になるけど、この手法なら将来的には結構な工数削減にも繋がる可能性もありそう。ただし、全員にとって万能とは限らないので、その点は少し注意した方がいいと思う。それでも今まで七十回近く同じ作業を繰り返していた人には、一つの選択肢として検討する余地はありそうだな、と感じたりする。
Comparison Table:
項目 | 内容 |
---|---|
データソース名抽出 | SQL文からテーブル名を正規表現で抽出する方法が重要。FROMやJOINの後ろにある名前を拾う必要がある。 |
柔軟なアプローチ | 完璧さよりも、状況に応じた柔軟性を持った方がミスを減らせることが多い。 |
カスタムSQL処理 | 複数のカスタムSQLクエリに対応し、それぞれの情報を行ごとにまとめる必要がある。 |
ネスト構造の平坦化 | データフレームからネストされたフィールド情報を抜き出し、整形する手順が求められる。 |
上流・下流関係の把握 | publishedDatasources経由で普通のテーブル一覧も収集可能だが、API制限に注意が必要。 |

手作業で直すのは時間の無駄!メタデータAPIで効率化しよう
さて、この前も似たような話を聞いた気がするんだけど、TableauのMetadata APIってやつにPythonで接続する方法をざっくりまとめてみる。なんだかちょっと前からTSCってライブラリがちらほら話題になってて、あれでAPI叩けるとか。まあ、それ自体は珍しくないけど。
たとえばデータソースが何個もゴロゴロしているTableauサイトにアクセスしたい場合があるよね。そういう時には、まずパーソナルアクセストークンというものを作らなきゃいけないみたい(この辺り、たまに忘れて手こずる人も)。設定の中でそれっぽい名前つけて発行しておくんだけど、そのトークン名とキー、それから使うサイト名(これも実際はいろんな呼び方されてたり)をスクリプト内に差し込むことになる。
ちなみに、「dub01.online.tableau.com」みたいなURLは一例で、人によって違うケースも多いかな。そのまま使うわけじゃなく、自分の環境用のアドレス入れる感じ。もし上手く認証できれば、「Connected」と出力窓に表示される……と思ったんだけど、環境次第ではもう少し待たされることもあったり。
ここまで来たら、本題はやっぱりデータソース一覧を引っ張ってくるところかもしれない。全部と言っても数十種類くらい? その中からIDや名前、あとオーナーの連絡先など最低限必要そうなのだけ拾えば十分な気がする。この部分、一部属性しか要らない場合も結構多いので、そのへん柔軟に調整可能だったような…。細かい仕様変更は割と起きやすいので、ときどきドキュメント眺め直す羽目になるかもしれない。
こういう流れで始めてみる人もちょこちょこいるようだし、一度動けば依存関係とかテーブル情報までざっくり見えて便利そう。ただし絶対的な万能感というよりは「状況によって役立つ」くらいの感覚が近かった印象だ。
たとえばデータソースが何個もゴロゴロしているTableauサイトにアクセスしたい場合があるよね。そういう時には、まずパーソナルアクセストークンというものを作らなきゃいけないみたい(この辺り、たまに忘れて手こずる人も)。設定の中でそれっぽい名前つけて発行しておくんだけど、そのトークン名とキー、それから使うサイト名(これも実際はいろんな呼び方されてたり)をスクリプト内に差し込むことになる。
ちなみに、「dub01.online.tableau.com」みたいなURLは一例で、人によって違うケースも多いかな。そのまま使うわけじゃなく、自分の環境用のアドレス入れる感じ。もし上手く認証できれば、「Connected」と出力窓に表示される……と思ったんだけど、環境次第ではもう少し待たされることもあったり。
ここまで来たら、本題はやっぱりデータソース一覧を引っ張ってくるところかもしれない。全部と言っても数十種類くらい? その中からIDや名前、あとオーナーの連絡先など最低限必要そうなのだけ拾えば十分な気がする。この部分、一部属性しか要らない場合も結構多いので、そのへん柔軟に調整可能だったような…。細かい仕様変更は割と起きやすいので、ときどきドキュメント眺め直す羽目になるかもしれない。
こういう流れで始めてみる人もちょこちょこいるようだし、一度動けば依存関係とかテーブル情報までざっくり見えて便利そう。ただし絶対的な万能感というよりは「状況によって役立つ」くらいの感覚が近かった印象だ。
GraphQLを使えば必要なデータだけピンポイントで取得できる
なんとなく、色んな情報をまとめておくためのリストを先に用意しておいたほうが楽だと感じる人もいるかもしれない。Tableauのサイトで公開中のデータソース一覧をざっくり取得する時って、下みたいなコードがよく使われてる。細かいAPI仕様までは今回は触れずに、どちらかと言えば「特定テーブルがどのデータソースに影響するか」を少し前向きに探す流れを重視している感じかな。
で、このMetadata APIだけど、結果はJSON形式でもらえることになっていて…実際どういう形になるかというと、ネストされたリストとか辞書とかが混じった構造になることが多い。項目によっては二重三重になってたりするし、DataFrameに変換しようとするとちょっと面倒だったりもするみたい。それこそ、「数件」くらいなら手作業でも追えるけど、「そこそこの数」ある場合は自動化した方が楽そう。
例えば今使っているクエリだと、得られる出力例(もちろんこれはサンプルで、本物とは違う部分も多々ある)はこんな感じ:
{
"data": {
"publishedDatasources": [
{
"name": "Sales Performance DataSource",
"id": "f3b1a2c4-1234-5678-9abc-1234567890ab",
"owner": {
"name": "Alice Johnson",
"email": "[email protected]"
}
},
...
]
}
}
こういうものから必要な情報だけ抜き出してDataFrame化するには、それぞれのオブジェクト内に入ってる所有者(owner)の名前やメールも上手く取り出す必要があったりする。まあ、それほど珍しい話でもないんだけど…。Pythonでやるなら、まずざっくり列名を拾って空DataFrame作成→各要素ごとに一行ずつconcatして…みたいな流れ。ownerフィールドから名前やメールアドレスだけ改めて列として切り出す処理もよく見かける。
最終的には、「全部で数件から十数件程度」のデータソース名・ID・所有者名・所有者メールアドレスの一覧表みたいなのが出来上がるイメージ。この時点ではまだ全体像把握用なので詳細分析はこれからという雰囲気かな。
ちなみに、「このマスター表」ができた後、その次の段階として各データソース内で利用されているテーブル名なんかを順番に調べていけばいい…みたいな流れになりやすいと思う。ただ、一部環境では仕様やバージョンによって細部挙動が異なることもあるので、その辺は適宜確認した方が無難そう。
で、このMetadata APIだけど、結果はJSON形式でもらえることになっていて…実際どういう形になるかというと、ネストされたリストとか辞書とかが混じった構造になることが多い。項目によっては二重三重になってたりするし、DataFrameに変換しようとするとちょっと面倒だったりもするみたい。それこそ、「数件」くらいなら手作業でも追えるけど、「そこそこの数」ある場合は自動化した方が楽そう。
例えば今使っているクエリだと、得られる出力例(もちろんこれはサンプルで、本物とは違う部分も多々ある)はこんな感じ:
{
"data": {
"publishedDatasources": [
{
"name": "Sales Performance DataSource",
"id": "f3b1a2c4-1234-5678-9abc-1234567890ab",
"owner": {
"name": "Alice Johnson",
"email": "[email protected]"
}
},
...
]
}
}
こういうものから必要な情報だけ抜き出してDataFrame化するには、それぞれのオブジェクト内に入ってる所有者(owner)の名前やメールも上手く取り出す必要があったりする。まあ、それほど珍しい話でもないんだけど…。Pythonでやるなら、まずざっくり列名を拾って空DataFrame作成→各要素ごとに一行ずつconcatして…みたいな流れ。ownerフィールドから名前やメールアドレスだけ改めて列として切り出す処理もよく見かける。
最終的には、「全部で数件から十数件程度」のデータソース名・ID・所有者名・所有者メールアドレスの一覧表みたいなのが出来上がるイメージ。この時点ではまだ全体像把握用なので詳細分析はこれからという雰囲気かな。
ちなみに、「このマスター表」ができた後、その次の段階として各データソース内で利用されているテーブル名なんかを順番に調べていけばいい…みたいな流れになりやすいと思う。ただ、一部環境では仕様やバージョンによって細部挙動が異なることもあるので、その辺は適宜確認した方が無難そう。

PythonでTableauサーバーに接続する最初の一歩
Tableauをよく使う人だったら、まあ気付いてると思うけど、データソースのテーブル選択って二通りあるんだよね。ひとつは普通にテーブルを何個かポチポチ選んで、それぞれ関係性(リレーション)を作っちゃう方法。もう一方はカスタムSQLで複数テーブルを繋いじゃって、そこから新しい結果テーブルみたいなものを出すやり方かな。
どうしても両方に対処しないといけない場面があるっぽい。たとえば、ここの例ではカスタムSQLがどこで使われてるのか、そのデータソース名も含めて一覧にしたいことになった。でも、全部まとめて見ると言っても、七十個とか百近くのクエリだけならまだしも、多分組織によってはそれより多そう。だから、「最初の五百件くらいまで」みたいな感じで制限かけて取得するパターンが載ってた。
もし五百以上あったら offset 使えばいいよ、と書いてあった気がする。それ以外にもカーソル方式?というページング手段もどこかで紹介されてたような…。ただここでは深追いせずに offset だけで充分だろう…という前提だった。
コード自体はPythonぽいやつで、多分サーバー認証してから GraphQL の customSQLTablesConnection を呼んでる感じ。ただ細かい話になるけど「本番環境だとデータもっとある可能性高いし、このままじゃ全部拾えない」と思う人もいるかもしれない。一応サンプルとして mock データ出力のイメージも添えてあったと思う。
情報の流れ的には、「このAPI叩いたらカスタムSQLごとの名前・id・紐付いてるデータソース・実際のクエリ内容」辺りが返ってきて、それ見ながら管理者とかが確認できるようになってる雰囲気だったかなぁ。全体的にはそんな難しく考えなくても、大枠こういう仕組み、と捉えておけば大丈夫そう。
どうしても両方に対処しないといけない場面があるっぽい。たとえば、ここの例ではカスタムSQLがどこで使われてるのか、そのデータソース名も含めて一覧にしたいことになった。でも、全部まとめて見ると言っても、七十個とか百近くのクエリだけならまだしも、多分組織によってはそれより多そう。だから、「最初の五百件くらいまで」みたいな感じで制限かけて取得するパターンが載ってた。
もし五百以上あったら offset 使えばいいよ、と書いてあった気がする。それ以外にもカーソル方式?というページング手段もどこかで紹介されてたような…。ただここでは深追いせずに offset だけで充分だろう…という前提だった。
コード自体はPythonぽいやつで、多分サーバー認証してから GraphQL の customSQLTablesConnection を呼んでる感じ。ただ細かい話になるけど「本番環境だとデータもっとある可能性高いし、このままじゃ全部拾えない」と思う人もいるかもしれない。一応サンプルとして mock データ出力のイメージも添えてあったと思う。
情報の流れ的には、「このAPI叩いたらカスタムSQLごとの名前・id・紐付いてるデータソース・実際のクエリ内容」辺りが返ってきて、それ見ながら管理者とかが確認できるようになってる雰囲気だったかなぁ。全体的にはそんな難しく考えなくても、大枠こういう仕組み、と捉えておけば大丈夫そう。
全データソースのリストをJSONからpandasに変換するコツ
えーと、前にもあったデータソースのリストを作る流れで、また似たような感じのネスト構造になってるJSONが出てきたんだけど。下流のデータソース名だけ抜き出したい場合、中身を全部見ていく必要があるみたい。SQL文もそのまま全部載ってるんだよね。正規表現で探そうとすると、テーブル名ってFROMとかJOINの後ろに必ずあるっぽいけど、なんか完全な形じゃなくて途中までしか取れないことも、時々あった気がする。例えばデータベース名とスキーマ名だけで止まっちゃうケースとか。
それからね、一つのデータソースに複数のカスタムSQLクエリがひもづいてるパターンも少なくないみたいだから、その場合は行ごとに内容まとめないと全体像が見えにくい気がする。でも実際どこまでやれば足りるかは場合によって違うかもしれないし、「絶対この方法なら大丈夫」とまでは言い切れないかな。
数字についてなんだけど、具体的な件数を書くより「七十ちょっと」「三割くらい」「かなり多め」みたいなふわっとした表現使った方が良さそうだし、それくらい大雑把でも十分伝わる場面もあると思う。
何回か同じような作業している中で、どうしても細部は曖昧になることがあった記憶。あと手順自体もちょっと順番変えて進めた方がやりやすかった、と感じたこともちらほら。全部きっちり決め打ちせず、ときどき戻って確認した方が結果的にはミス減らせたりするかもしれないね。
まあ、とにかくテーブル名抽出やデータソースまとめ作業については、「完璧」より「そこそこ柔軟」に考えておいた方が安心できる気がしてくる。

カスタムSQLクエリに隠れたテーブル名を正規表現で抽出する方法
カスタムSQLのレスポンスをデータフレームに変換するやり方について、ちょっと複雑な手順がいくつかあるみたい。まず、なんとなく数個か十数個くらいのカラム名を取得して、それを使って空っぽのデータフレームを作ることから始める。で、そのあと各ノードごとに少しずつデータを追加していく。たぶん全部合わせてもそこまで膨大な量にはならないけど、途中で何度もデータフレーム同士を結合したりしているので、うまく工夫しないと時間がかかることも。
途中、「downstreamDatasources」から名前らしきものだけ取り出す部分があって、ここは一部しか情報が入ってこない場合もありそうだなと思った。ただ、不完全だったらNoneとかになってしまうので注意しておいた方が良さそう。
それから、SQL文からテーブル名だけ抽出したい時には正規表現(regex)を使うことになるらしい。「FROM」とか「JOIN」の後ろに来る名前だけ拾う感じ。でも、このテーブル名ってたまに「倉庫名.スキーマ.テーブル」みたいなフォーマットになったりするので、その辺も含めてパターンを書き換える必要が出てきたりする。どうやら重複排除はされているみたい。
で、「customSQLTables」カラムとしてこの抽出結果を保存。そのあと「data_source」ごとにまとめ直している様子。同じデータソース内で複数のカスタムSQLテーブルが使われているケースもあるっぽいので、一応リスト化&ユニーク化しておくとのこと。
全体の流れとしては、「custom SQL が使われているデータソース」が七つ八つとかその程度見つかった時点で終了かな。
さて、この先なんだけど…今度は「普通のテーブル」、つまりカスタムSQLじゃなく直接参照されてるテーブル一覧も集めたいという話になる。ただ、その方法にも二通りくらいあるようで。一方では「publishedDatasources」というオブジェクト経由でもう一方では「DatabaseTable」経由。それぞれ上流・下流関係を見る場所が違うんだと思うけど、とりあえず今回は前者——つまりpublishedDatasources経由——を選択してる感じ。
理由としては、多分データソース単位で見やすくなるからだろうね。これなら特定のひとつひとつ(例えば気になるもの)だけ詳細調査したい時にも転用できそうだから便利なのかもしれない。
ただしちょっと面倒なのは、「fields」というフィールド配下にしか上流テーブル情報が入ってこない仕様。そのため、もし一つのDS内に百項目くらいフィールドが存在すると……APIレスポンス制限的な問題も発生しかねない状況。ただまあ、本当に大量じゃなければそこまで困らないとは思いたいところ。
ここではmaster_dfというリストっぽいやつからDS名(多分数十件程度?)取り出し、それぞれループ処理。このへん多少冗長でも確実性優先なんだろうね。サーバー認証付きでGraphQLクエリ投げ込む形になっていて、その中身はds_name指定して各種属性+fields配下まで丸ごと取得する形。そのあと辞書化→json変換→また結合……という地味な工程繰り返すイメージ。
最後にはindex振り直して終了、と。でもこの段階じゃまだネスト構造抜け切れてなくて、「fields」の中身平坦化&フィールド名やテーブル名抜き出す作業までは残ったままになってる雰囲気だったかな……
途中、「downstreamDatasources」から名前らしきものだけ取り出す部分があって、ここは一部しか情報が入ってこない場合もありそうだなと思った。ただ、不完全だったらNoneとかになってしまうので注意しておいた方が良さそう。
それから、SQL文からテーブル名だけ抽出したい時には正規表現(regex)を使うことになるらしい。「FROM」とか「JOIN」の後ろに来る名前だけ拾う感じ。でも、このテーブル名ってたまに「倉庫名.スキーマ.テーブル」みたいなフォーマットになったりするので、その辺も含めてパターンを書き換える必要が出てきたりする。どうやら重複排除はされているみたい。
で、「customSQLTables」カラムとしてこの抽出結果を保存。そのあと「data_source」ごとにまとめ直している様子。同じデータソース内で複数のカスタムSQLテーブルが使われているケースもあるっぽいので、一応リスト化&ユニーク化しておくとのこと。
全体の流れとしては、「custom SQL が使われているデータソース」が七つ八つとかその程度見つかった時点で終了かな。
さて、この先なんだけど…今度は「普通のテーブル」、つまりカスタムSQLじゃなく直接参照されてるテーブル一覧も集めたいという話になる。ただ、その方法にも二通りくらいあるようで。一方では「publishedDatasources」というオブジェクト経由でもう一方では「DatabaseTable」経由。それぞれ上流・下流関係を見る場所が違うんだと思うけど、とりあえず今回は前者——つまりpublishedDatasources経由——を選択してる感じ。
理由としては、多分データソース単位で見やすくなるからだろうね。これなら特定のひとつひとつ(例えば気になるもの)だけ詳細調査したい時にも転用できそうだから便利なのかもしれない。
ただしちょっと面倒なのは、「fields」というフィールド配下にしか上流テーブル情報が入ってこない仕様。そのため、もし一つのDS内に百項目くらいフィールドが存在すると……APIレスポンス制限的な問題も発生しかねない状況。ただまあ、本当に大量じゃなければそこまで困らないとは思いたいところ。
ここではmaster_dfというリストっぽいやつからDS名(多分数十件程度?)取り出し、それぞれループ処理。このへん多少冗長でも確実性優先なんだろうね。サーバー認証付きでGraphQLクエリ投げ込む形になっていて、その中身はds_name指定して各種属性+fields配下まで丸ごと取得する形。そのあと辞書化→json変換→また結合……という地味な工程繰り返すイメージ。
最後にはindex振り直して終了、と。でもこの段階じゃまだネスト構造抜け切れてなくて、「fields」の中身平坦化&フィールド名やテーブル名抜き出す作業までは残ったままになってる雰囲気だったかな……
通常のテーブル参照とカスタムSQLを統合して影響分析を行う
テーブル名って、まあまあ何度も出てくることが多いんだよね。だから重複しちゃう分は一応整理しておいたほうがいい感じかもしれない。Pythonで書くとき、多分こんな風にやる人もいるんじゃないかな、と。
たとえば「fields」とか「upstreamTables」みたいな情報をリストから取り出す関数を書くことになる。名前を抜き出したり、「upstreamTables」に入っているものを集めたり。ちなみに、「ds_df['fields']」なんかは大体辞書っぽい形で保存されてる場合がほとんどだから、そのままだとちょっと扱いづらいかも? それでast.literal_eval()とか使って無理やり変換してるケース、ちらほら見たような気がする。
話は少し飛ぶけど、「upstreamTables」の値を本当に全部抜き出すには、ネストされたリストの中身を結構地道に回して確認しないとだめだった記憶がある。その時点ですでに十個前後のテーブル名とか見つかったりすることもあった。もちろん全部一意にしておくべきだからset型使って被りを消す感じになる。
列の整理が終わったあと、「index」とか「fields」みたいなのはもう必要なくなるからドロップしてしまう例もあるみたい。それぞれの処理について、何となく実際触った人ならピンと来る部分も多そう。
さて、それら全部片付いたタイミングで、「ds_df」がどうなるかというと…サンプルを見る限りでは、テーブル名やフィールド一覧、それから上流テーブル情報なんかがずらっと並ぶ感じになってた印象(詳細は手元データ次第だけど)。この段階でもうほぼ欲しい情報は揃いつつある。
その後だけど、最後にマージ処理が待っている。「master_df」「ds_df」、それから「cs_df」を左結合した結果、新しいDataFrame「master_data」ができる。このあたりになるともしかすると三つほどデータソースの組み合わせパターンくらい見えてくる場面もしばしば。
エクセル形式への保存まで行えば、一通り分析用データとして加工完了。ただ、本当に便利なのはここから先。「Sales」テーブルみたいにスキーマ変更が入った時、影響範囲チェックしたくなる時あるじゃない? そんな時用の関数を書いておけば、「upstreamTables」や「customSQLTables」の中に特定の名前(部分一致含む)があれば、その行ごと抜き出せる仕組みにできている場合も見受けられる。
実例として試したところ、大体三つくらい関連データソースが引っ掛かった感じだったと思う。こういう風に抽出できれば、オーナーさん——例えばアリスさんとかボブさん——にも前もって伝えておいて、大ごとになる前に準備進めてもらいやすい環境作れるかな、と考えられているようだね。
コード全体についてはGitHubなどにもまとめて公開されている事例もちょこちょこ増えてきている様子だけれど、本格的な運用には多少調整や追加検証も要る場面ありそう。必ずしも全員同じ方法ではまわしてはいないようなので、一部ユーザー限定で効果的だったという話を聞いたこともあった気がする……
たとえば「fields」とか「upstreamTables」みたいな情報をリストから取り出す関数を書くことになる。名前を抜き出したり、「upstreamTables」に入っているものを集めたり。ちなみに、「ds_df['fields']」なんかは大体辞書っぽい形で保存されてる場合がほとんどだから、そのままだとちょっと扱いづらいかも? それでast.literal_eval()とか使って無理やり変換してるケース、ちらほら見たような気がする。
話は少し飛ぶけど、「upstreamTables」の値を本当に全部抜き出すには、ネストされたリストの中身を結構地道に回して確認しないとだめだった記憶がある。その時点ですでに十個前後のテーブル名とか見つかったりすることもあった。もちろん全部一意にしておくべきだからset型使って被りを消す感じになる。
列の整理が終わったあと、「index」とか「fields」みたいなのはもう必要なくなるからドロップしてしまう例もあるみたい。それぞれの処理について、何となく実際触った人ならピンと来る部分も多そう。
さて、それら全部片付いたタイミングで、「ds_df」がどうなるかというと…サンプルを見る限りでは、テーブル名やフィールド一覧、それから上流テーブル情報なんかがずらっと並ぶ感じになってた印象(詳細は手元データ次第だけど)。この段階でもうほぼ欲しい情報は揃いつつある。
その後だけど、最後にマージ処理が待っている。「master_df」「ds_df」、それから「cs_df」を左結合した結果、新しいDataFrame「master_data」ができる。このあたりになるともしかすると三つほどデータソースの組み合わせパターンくらい見えてくる場面もしばしば。
エクセル形式への保存まで行えば、一通り分析用データとして加工完了。ただ、本当に便利なのはここから先。「Sales」テーブルみたいにスキーマ変更が入った時、影響範囲チェックしたくなる時あるじゃない? そんな時用の関数を書いておけば、「upstreamTables」や「customSQLTables」の中に特定の名前(部分一致含む)があれば、その行ごと抜き出せる仕組みにできている場合も見受けられる。
実例として試したところ、大体三つくらい関連データソースが引っ掛かった感じだったと思う。こういう風に抽出できれば、オーナーさん——例えばアリスさんとかボブさん——にも前もって伝えておいて、大ごとになる前に準備進めてもらいやすい環境作れるかな、と考えられているようだね。
コード全体についてはGitHubなどにもまとめて公開されている事例もちょこちょこ増えてきている様子だけれど、本格的な運用には多少調整や追加検証も要る場面ありそう。必ずしも全員同じ方法ではまわしてはいないようなので、一部ユーザー限定で効果的だったという話を聞いたこともあった気がする……

Salesテーブル変更時の影響範囲を特定する実践的なフィルタリング術
TableauのメタデータAPIって、実は色々な場面で役立てられるみたいだ。例えばカスタムSQLで使われてるフィールド名をなんとなく抽出して、まあそこから何かしらの影響分析っぽいものができたりすることもあるんじゃないかと思う。いや、全部が全部そう簡単に行くとも言えないけど。
あと、「extractLastUpdateTime」ってやつをちょっと見ておけば、しばらく誰も触ってなさそうなデータソースとかに気付いたりすることもあるね。もう長い間更新されてないものなんかは、場合によっては整理した方が良いかもしれない。でも本当にそれが不要なのかどうか、たまに迷ったりもする。
ダッシュボードについてもちょっと調べようと思えば、「dashboards」というオブジェクトから断片的な情報を拾える時がある。ただ、それだけじゃ全体像までは把握しきれないことも多いかな。
振り返ると、この手の自動化には他にもまだまだ色んなネタが隠れてる気がしてきた。もしここまで読んだ人がいたとしたら、その人の日常業務にも何かヒントになる部分があった…という可能性はなくもないよね。まあ、自分自身でも似たようなことを考え直すタイミングだったかもしれない。このちょっとしたプロジェクトでTableauメタデータAPIの面白さや使い道っぽいものを少し体感できたなら、それだけでも十分だったかな、と今になって思う。
ちなみに、大きめのデータセットに関して悩んだ話とか、他にも書いたブログ記事みたいなのもあった気がするけど…まぁ、その辺りは興味あれば探してみてもいいかもしれないね。
あと、「extractLastUpdateTime」ってやつをちょっと見ておけば、しばらく誰も触ってなさそうなデータソースとかに気付いたりすることもあるね。もう長い間更新されてないものなんかは、場合によっては整理した方が良いかもしれない。でも本当にそれが不要なのかどうか、たまに迷ったりもする。
ダッシュボードについてもちょっと調べようと思えば、「dashboards」というオブジェクトから断片的な情報を拾える時がある。ただ、それだけじゃ全体像までは把握しきれないことも多いかな。
振り返ると、この手の自動化には他にもまだまだ色んなネタが隠れてる気がしてきた。もしここまで読んだ人がいたとしたら、その人の日常業務にも何かヒントになる部分があった…という可能性はなくもないよね。まあ、自分自身でも似たようなことを考え直すタイミングだったかもしれない。このちょっとしたプロジェクトでTableauメタデータAPIの面白さや使い道っぽいものを少し体感できたなら、それだけでも十分だったかな、と今になって思う。
ちなみに、大きめのデータセットに関して悩んだ話とか、他にも書いたブログ記事みたいなのもあった気がするけど…まぁ、その辺りは興味あれば探してみてもいいかもしれないね。
メタデータAPI活用事例をもっと知りたい人への追加リソース
そういえば、前にPythonとStreamlit、それからSQLiteをちょっと使ってアプリっぽいものを作った話を書いた気がする。あれはゼロから始めて、データベースで動く仕組みだったかな、多分。興味ある方は、昔のブログも覗いてみるといいかもしれない。
最近だとTableauでビッグデータを扱うダッシュボードについて色々試してみたけど、やっぱり一筋縄ではいかない部分があったような…。細かい問題とか予想外の工夫が必要な場面が何度も出てきて、その都度学ぶことがちらほら。でも全部順調だったわけでもなくて、「これ本当に大丈夫かな?」と思う瞬間も実際には少なくなかった気がする。
ところで、自分の記事って七十本も無いんだけど、時々見てくれてる人いるみたい。Mediumのプロフィールページに過去記事まとめてあるので、一応案内だけ書いておく感じです。新しい投稿のお知らせもフォローしておけば届くかもしれないし。
あとTwitterとかLinkedInとかでも繋がれるっぽいですが、そちらは内容によって反応遅れるかもしれませんので…その辺はご容赦くださいね。まあ、大体そんな感じだったと思います。
最近だとTableauでビッグデータを扱うダッシュボードについて色々試してみたけど、やっぱり一筋縄ではいかない部分があったような…。細かい問題とか予想外の工夫が必要な場面が何度も出てきて、その都度学ぶことがちらほら。でも全部順調だったわけでもなくて、「これ本当に大丈夫かな?」と思う瞬間も実際には少なくなかった気がする。
ところで、自分の記事って七十本も無いんだけど、時々見てくれてる人いるみたい。Mediumのプロフィールページに過去記事まとめてあるので、一応案内だけ書いておく感じです。新しい投稿のお知らせもフォローしておけば届くかもしれないし。
あとTwitterとかLinkedInとかでも繋がれるっぽいですが、そちらは内容によって反応遅れるかもしれませんので…その辺はご容赦くださいね。まあ、大体そんな感じだったと思います。