📙

Tableau Prepを使ったSQLトレースを行い、快適なフロー設計を考える

2021/08/01に公開

Tableau Prepを使ったSQLトレースを行い、快適なフロー設計を考える

Tableauでプリセールスエンジニアをしている @rsugimura17 です。今回はTableau Prep Builder、Tableau Prep Conductor のSQL トレースを行い、快適なフロー設計を考えていきます。

Tableau Prepとは?

データを結合、分析に適した形式へ変換、クリーニングするためのビジュアルかつ直接的な方法を提供する Tableau のデータ変換製品です。オンプレミスでもクラウドでも、データベースまたはスプレッドシートのどこにあってもデータに接続でき、多種多様なデータへのアクセス、組み合わせ、クリーニングがコーディングなしで行えます。Tableau Prep は2つの製品で構成されています。データフローを構築するための Tableau Prep Builder、そして組織全体でフローをスケジュール、監視、管理するための Tableau Prep Conductor です。

https://www.tableau.com/ja-jp/products/prep

Tableau 2020.3 ではTableau Prepの外部データベースへの書き込み、Tableau 2020.4 ではTableau Prep Builder がブラウザで使用できるようになるなど、続々と新機能が追加されています。

https://www.tableau.com/ja-jp/about/blog/2020/7/introducing-tableau-prep-write-database

https://www.tableau.com/ja-jp/blog/2020/12/tableau-prep-builder-now-available-browser

Tableau Prepを使ったDB接続のSQLトレース

Tableau Prep の公式ページでは以下のように述べられています。

Tableau Prep Builder は可能だと判断した処理をすべてデータベースで実行させるので、既存のデータベースを利用したままフローの実行で高速パフォーマンスを実現できます。

SQL トレースで明らかにしたいのは「可能だと判断した処理をすべてデータベースで実行させる」という点です。

Tableau Prep はSQL を意識せずにGUIでデータの変換処理ができるため、処理が行われる場所を考えずに重い処理を行わせてしまうことがあります。その結果、Tableau Prepは処理が重たいという声も見てきました。このSQL トレースをきっかけに、Tableau Prep のアーキテクチャを理解し、快適に使用する方法が伝われば嬉しく思います。

SQL トレースでは、Google BigQuery を使いながら、クラウドDWHを使用した場合の処理について見ていきます。Tableau Prep のフロー作成と実行はTableau Online 上で行います。

(1) Tableau Prep から BigQueryへの接続

Tableau Prep からBigQuery に接続を行い、テーブルをフロー内にドラッグ&ドロップで選択します。

BigQuery のクエリ履歴を見てみると、すべての列項目が選択されて、LIMIT 3 が指定されて行数をフィルターしたSELECT 文が実行されています。

SELECT `aa3b9d79-d117-47e7-8d98-d404fb`.`Row_ID` AS `Row_ID`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Category` AS `Category`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Discount` AS `Discount`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Ship_Date` AS `Ship_Date`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Customer_Name` AS `Customer_Name`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Product_ID` AS `Product_ID`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Return_Notes` AS `Return_Notes`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Segment` AS `Segment`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Ship_Mode` AS `Ship_Mode`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Sales` AS `Sales`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Days_to_Ship` AS `Days_to_Ship`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Return_Reason` AS `Return_Reason`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Product_Name` AS `Product_Name`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Quantity` AS `Quantity`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Order_Date` AS `Order_Date`,
  3 AS `hwmtableauinternal`
FROM `pre-sales-demo.JPN_Superstore`.`Superstore` `aa3b9d79-d117-47e7-8d98-d404fb`
LIMIT 3 

(2) クリーニングステップを追加する

データの全体像を把握できるクリーニングステップを追加します。BigQuery のクエリ履歴を参照すると、同一のクエリ文が発行されて、LIMIT 3 から LIMIT 226415 にクエリ行数が増えて、データのプロファイルが行われます。

余談ですが、Google BigQuery ではLIMIT 句を SELECTクエリに適用しても、読み取られるデータの量には影響しないため、クエリ量を少なくするには必要な列のみをクエリすることが求められます。BigQueryがデータソースの場合は必ず(3)の手順を先に行ってください。

SELECT `aa3b9d79-d117-47e7-8d98-d404fb`.`Row_ID` AS `Row_ID`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Category` AS `Category`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Discount` AS `Discount`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Ship_Date` AS `Ship_Date`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Customer_Name` AS `Customer_Name`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Product_ID` AS `Product_ID`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Return_Notes` AS `Return_Notes`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Segment` AS `Segment`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Ship_Mode` AS `Ship_Mode`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Sales` AS `Sales`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Days_to_Ship` AS `Days_to_Ship`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Return_Reason` AS `Return_Reason`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Product_Name` AS `Product_Name`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Quantity` AS `Quantity`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Order_Date` AS `Order_Date`,
  3 AS `hwmtableauinternal`
FROM `pre-sales-demo.JPN_Superstore`.`Superstore` `aa3b9d79-d117-47e7-8d98-d404fb`
LIMIT 226415 

(3) データ入力時点でデータサンプル量の指定と不要な列の削除を行う

Tableau Prep のパフォーマンスのベストプラクティスでは、データ入力時点でデータサンプル行数の指定と不要な列の削除が推奨されています。ベストプラクティス通りに処理を行います。BigQuery のクエリ履歴を参照すると、Tableau からBigQuery にクエリした列を減らすことができています。

データソースがBigQuery の場合はクエリのできるだけ早い段階でフィルタリングを行うことで、BigQuery のコストを削減できます。今回はSQLトレースが目的のために、(2) の処理を先に試してクエリを参照しましたが、BigQuery の場合はクリーニングステップに入る前に必ず(3) を行います。

※データのサンプリングはTableau Prep フロー内に表示されるデータの行数であり、データの出力時はすべてのデータが対象となります。

ここまでのすべての処理は、DB 側にクエリが発行されて計算処理が行われています。

SELECT `aa3b9d79-d117-47e7-8d98-d404fb`.`Category` AS `Category`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Customer_Name` AS `Customer_Name`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Quantity` AS `Quantity`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Order_Date` AS `Order_Date`,
  3 AS `hwmtableauinternal`
FROM `pre-sales-demo.JPN_Superstore`.`Superstore` `aa3b9d79-d117-47e7-8d98-d404fb`
LIMIT 10000

(4) データのフィルターを行う

Tableau Prep のクリーニングステップで、Category のOffice Supplies のみをフィルターします。BigQuery のクエリ履歴を参照すると、新規のクエリは発行されていませんでした。(2) 、(3) で実行した結果をTableau Prep 内でキャッシュし、ローカルのテンポラリHyper を利用して処理をかけていることがわかります。

(4) の時点ではBigQuery のコンピューティングリソースは使わずに、Tableau 内で処理を行うため、(3) のデータのサンプル量の指定や列の削除を行うことがいかに重要かがわかります。

Tableau Prepのフロー編集時にテンポラリ
Hyper を生成して処理を行うアーキテクチャにより、BigQuery に対して過剰なクエリ発行を行わず、クエリ課金を避けられるということが言えます。

(5) データの集計を行う

Tableau Prep のフローにデータの集計を追加して、Category、Customer_NameごとにQuantity を集計するという処理を加えてみます。BigQuery のクエリ履歴を見ると、クエリは新たに発行されていませんでした。(4) から続いて、(3) で取得したBigQuery のクエリ結果をキャッシュとして継続して使いながら、処理を行っていることがわかります。

(6) フローの実行を行う

Tableau Prep のデータ変換処理を終えて、フローの実行を行います。BigQuery のクエリ履歴を参照すると、BigQuery に新たにクエリが発行されて、(4) のデータのフィルターはWHERE句に、(5) のデータの集計もGROUP BYでBigQueryにプッシュダウンできていることが確認できます。

SELECT `aa3b9d79-d117-47e7-8d98-d404fb`.`Category` AS `Category`,
  `aa3b9d79-d117-47e7-8d98-d404fb`.`Customer_Name` AS `Customer_Name`,
  SUM(CAST(`aa3b9d79-d117-47e7-8d98-d404fb`.`Quantity` AS INT64)) AS `Quantity`
FROM `pre-sales-demo.JPN_Superstore`.`Superstore` `aa3b9d79-d117-47e7-8d98-d404fb`
WHERE (`aa3b9d79-d117-47e7-8d98-d404fb`.`Category` = 'Office Supplies')
GROUP BY 1,
  2

他のDWH サービスSnowflake でも検証したところ同一の内容となったため、Tableau Prep フローを完成させて、フローの実行や更新を行う場合は、Tableau Prep Builder で可能だと判断された処理はすべてデータベースで実行させることができ、クラウドDWH の高速なコンピューティングリソースを使いながらデータの変換処理を行うことが確認できました。

SQLトレースから言える快適なフロー設計に必要なこと

Tableau Prep のフロー作成、編集時の処理の場所と、フロー実行、更新時の処理の場所が異なることがわかりました。

Tableau Prep のフローを完成させてしまえば、DB側に処理をプッシュダウンさせることができるため、BigQuery やSnowflake といった高速なクラウドDWHを使った場合は快適なフロー実行と更新が期待できます。

気をつけなければならないことは、Tableau Prep のフロー作成と編集時にTableau にキャッシュされたデータの処理をいかに快適に行うかが大切です。

Tableau Prep フロー作成、編集時

Tableau Prep フロー実行、更新時

Tableau Prep のフロー作成、編集時に押さえておきたいポイント

SQL トレースを行うことで、Tableau Prep の処理の仕組みがわかってきました。Tableau Prep のフロー作成、編集時に押さえておきたいポイントを見ていきます。

詳しくは参照リンク先をご確認ください。

  1. サンプルで利用するデータ量を減らしてフロー設計作業をスピードアップ
  2. 出来るだけ早い段階で必要なデータに絞り込む
  3. 分析に必要なレベルにデータを集計する
  4. 集計処理と結合処理がある場合は、集計処理を先に行う

重要なことなので何度も書きますが、1.のデータのサンプリングはTableau Prep フロー内に表示されるデータの行数であり、データの出力時はすべてのデータが対象となります。

Tableau Prepのフロー内でデータのプロファイルを行う必要がなければ、サンプル量はできるだけ絞るようにしましょう。

https://www.tableau.com/ja-jp/about/blog/2018/11/three-tips-in-flow-design-to-use-tableau-prep-easily-98758

Best Practices for Flow Performance in Data Prep

Tableau Conference 2019 でもTableau Prep のフローパフォーマンスのベストプラクティスセッションからtips がいくつか紹介されています。

  1. 結合処理とその他処理を混ぜない

  1. クロスDB結合は避けたほうが良い
    クロスDB結合はすべてのデータ変換処理をDB側で完結させることができず、Tableau内でHyper 同士の結合処理が行われます。

  1. 数値型のほうが文字型より処理が早い

https://tc19.tableau.com/learn/sessions/best-practices-flow-performance-data-prep

まとめ

Tableau Prep Builder 、Tableau Prep Conductor のSQL トレースを紹介させていただきました。Tableau Prep を使うときに、処理が行われている場所を理解した上で、適切な使い方ができれば、快適にフロー設計を行うことができるはずです。

Tableau Prep Builder、Conductorのフロー実行、更新の処理がDB 側にプッシュダウンされて、クラウドDWH の恩恵を大きく受けられるアーキテクチャであることを多くの方に知っていただける機会となれば嬉しく思います。今後もTableau Prep の機能拡張に期待です。

リソース

本記事に関する詳細については、次のリソースを参照してください。

Discussion