dbt on Treasure Data with dbt-presto の動作確認をした

サマリー

  • dbt が Treasure Data で動くか試してみた。
  • 結果としては dbt-presto の修正が必要そうで現状のままでは動作しないことが確認できた。
  • 果たして dbt-presto に Treasure Data に合うようなモードを追加するのが良いか、 dbt-athena のように別なプラグインとして提供するのが良いか。

dbt on Presto

以前の記事で少し触れたように dbt は Presto 用のプラグイン dbt-presto を用意しており、現時点では一部機能のみ使用することが可能である。

Due to the nature of Presto, not all core dbt functionality is supported. The following features of dbt are not implemented on Presto: 1. Snapshots 2. Incremental models

Presto Profile | dbt Docs

Trino でも問題なく動くようだ。

Trino + dbt = a match in SQL heaven? | by Victor Coustenoble | Geek Culture | Jun, 2021 | Medium

動作確認手順

インストール

dbt, dbt-presto をインストールし、プロジェクトを作成する。

$ python3 -m venv venv
$ source venv/bin/activate
$ pip install dbt-presto
$ dbt --version
installed version: 0.20.0
   latest version: 0.20.0

Up to date!

Plugins:
  - presto: 0.20.0
$ dbt init dbt-td-sample --adapter presto
Running with dbt=0.20.0
Creating dbt configuration folder at /Users/satoshi.hirose/.dbt
With sample profiles.yml for presto

Your new dbt project "dbt-td-sample" was created! If this is your first time
using dbt, you'll need to set up your profiles.yml file (we've created a sample
file for you to connect to presto) -- this file will tell dbt how
to connect to your database. You can find this file by running:

  open /Users/satoshi.hirose/.dbt

For more information on how to configure the profiles.yml file,
please consult the dbt documentation here:

  https://docs.getdbt.com/docs/configure-your-profile

One more thing:

Need help? Don't hesitate to reach out to us via GitHub issues or on Slack --
There's a link to our Slack group in the GitHub Readme. Happy modeling!

接続情報の追加

Treasure Data への接続方法を確認しながら ~/.dbt/profiles.yml を修正する。

JDBC Driver for Presto - Product Documentation - Treasure Data Product Documentation

td:
  target: dev
  outputs:
    dev:
      type: presto
      method: none  # optional, one of {none | ldap | kerberos}
      user: <your api key>
      password: dummy
      database: td-presto
      host: api-presto.treasuredata.com
      port: 443
      schema: satoshihirose
      threads: 1

dbt debug の実行

dbt debug を試してみるとエラーが発生する。

$ cd dbt-td-sample
$ dbt debug --profile td
Running with dbt=0.20.0
dbt version: 0.20.0
python version: 3.9.6
python path: /Users/satoshi.hirose/work/dbt-td-sample/venv/bin/python3.9
os info: macOS-11.2.3-x86_64-i386-64bit
Using profiles.yml file at /Users/satoshi.hirose/.dbt/profiles.yml
Using dbt_project.yml file at /Users/satoshi.hirose/work/dbt-td-sample/dbt-td-sample/dbt_project.yml

Configuration:
  profiles.yml file [OK found and valid]
  dbt_project.yml file [OK found and valid]

Required dependencies:
 - git [OK found]

Connection:
  host: api-presto.treasuredata.com
  port: 443
  user: 7060/67d84dbef2b34a9f10ac5d7da8022e8a9d772aed
  database: td-presto
  schema: satoshihirose
  Connection test: ERROR

dbt was unable to connect to the specified database.
The database returned the following error:

  >Runtime Error
  error 400: b'<html>\r\n<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>\r\n<body>\r\n<center><h1>400 Bad Request</h1></center>\r\n<center>The plain HTTP request was sent to HTTPS port</center>\r\n</body>\r\n</html>\r\n'

Check your database credentials and try again. For more information, visit:
https://docs.getdbt.com/docs/configure-your-profile

どうやら https で接続していないことが問題のようだ。

確認をすると dbt-presto は auth が none の時は http 接続をするようハードコードされており、設定などでは対応できないようだ。プラグインのコードを https に書き換えて先に進む。

https://github.com/dbt-labs/dbt-presto/blob/cc834028f8120784829cc66733007dbabcec1a30/dbt/adapters/presto/connections.py#L152-L163

接続することは確認できた。

(venv) [/Users/satoshi.hirose/work/dbt-td-sample/dbt-td-sample]dbt debug --profile td
Running with dbt=0.20.0
dbt version: 0.20.0
python version: 3.9.6
python path: /Users/satoshi.hirose/work/dbt-td-sample/venv/bin/python3.9
os info: macOS-11.2.3-x86_64-i386-64bit
Using profiles.yml file at /Users/satoshi.hirose/.dbt/profiles.yml
Using dbt_project.yml file at /Users/satoshi.hirose/work/dbt-td-sample/dbt-td-sample/dbt_project.yml

Configuration:
  profiles.yml file [OK found and valid]
  dbt_project.yml file [OK found and valid]

Required dependencies:
 - git [OK found]

Connection:
  host: api-presto.treasuredata.com
  port: 443
  user: 7060/67d84dbef2b34a9f10ac5d7da8022e8a9d772aed
  database: td-presto
  schema: satoshihirose
  Connection test: OK connection ok

dbt run の実行

次は dbt run を実行してみるとエラーが発生する。トランザクション周りで問題が発生している。

(venv) [/Users/satoshi.hirose/work/dbt-td-sample/dbt-td-sample]dbt run --profile td
Running with dbt=0.20.0
Found 2 models, 4 tests, 0 snapshots, 0 analyses, 145 macros, 0 operations, 0 seed files, 0 sources, 0 exposures

Encountered an error:
Runtime Error
  Runtime Error
    PrestoUserError(type=USER_ERROR, name=NOT_SUPPORTED, message="Nested transactions not supported", query_id=20210727_130455_32322_s2qyv)

デバッグログを確認してみると、information schema は取得できているっぽいが、start transaction が失敗しているっぽい。TD のコンソールでクエリの実行状況を見ても同様の事象が確認できる。

$ dbt --debug run --profile td
...
2021-07-27 13:05:20.472157 (MainThread): Acquiring new presto connection "model.my_new_project.my_first_dbt_model".
2021-07-27 13:05:20.480174 (MainThread): Acquiring new presto connection "model.my_new_project.my_second_dbt_model".
2021-07-27 13:05:20.539955 (MainThread): Sending event: {'category': 'dbt', 'action': 'load_project', 'label': '728c6762-9aca-4330-bc3b-3840456a8980', 'context': [<snowplow_tracker.self_describing_json.SelfDescribingJson object at 0x10ceeac40>]}
2021-07-27 13:05:20.543735 (MainThread): Sending event: {'category': 'dbt', 'action': 'resource_counts', 'label': '728c6762-9aca-4330-bc3b-3840456a8980', 'context': [<snowplow_tracker.self_describing_json.SelfDescribingJson object at 0x10ceead00>]}
2021-07-27 13:05:20.543977 (MainThread): Found 2 models, 4 tests, 0 snapshots, 0 analyses, 145 macros, 0 operations, 0 seed files, 0 sources, 0 exposures
2021-07-27 13:05:20.544701 (MainThread):
2021-07-27 13:05:20.544973 (MainThread): Acquiring new presto connection "master".
2021-07-27 13:05:20.545602 (ThreadPoolExecutor-0_0): Acquiring new presto connection "list_td-presto".
2021-07-27 13:05:20.555404 (ThreadPoolExecutor-0_0): Using presto connection "list_td-presto".
2021-07-27 13:05:20.555564 (ThreadPoolExecutor-0_0): On list_td-presto: select distinct schema_name
    from "td-presto".INFORMATION_SCHEMA.schemata
2021-07-27 13:05:20.555703 (ThreadPoolExecutor-0_0): Opening a new connection, currently in state init
2021-07-27 13:05:27.149112 (ThreadPoolExecutor-0_0): SQL status: OK in 6.59 seconds
2021-07-27 13:05:27.153038 (ThreadPoolExecutor-0_0): On list_td-presto: Close
2021-07-27 13:05:27.154223 (ThreadPoolExecutor-1_0): Acquiring new presto connection "list_td-presto_satoshihirose".
2021-07-27 13:05:27.159687 (ThreadPoolExecutor-1_0): Opening a new connection, currently in state closed
2021-07-27 13:05:28.579790 (ThreadPoolExecutor-1_0): Error while running:
handle.start_transaction()
2021-07-27 13:05:28.580094 (ThreadPoolExecutor-1_0): PrestoUserError(type=USER_ERROR, name=NOT_SUPPORTED, message="Nested transactions not supported", query_id=20210727_130528_32356_s2qyv)
2021-07-27 13:05:28.580380 (ThreadPoolExecutor-1_0): Error while running:
macro list_relations_without_caching
2021-07-27 13:05:28.580660 (ThreadPoolExecutor-1_0): Runtime Error
  PrestoUserError(type=USER_ERROR, name=NOT_SUPPORTED, message="Nested transactions not supported", query_id=20210727_130528_32356_s2qyv)
2021-07-27 13:05:28.581073 (ThreadPoolExecutor-1_0): On list_td-presto_satoshihirose: Close
...

どうやら TD が start transaction をサポートしていないのが原因のようだ。

プラグインの start transaction を発行している箇所をコメントアウトして実行してみる。

dbt-presto/connections.py at cc834028f8120784829cc66733007dbabcec1a30 · dbt-labs/dbt-presto · GitHub

先に進んだ。次は、View が作れないことが原因のエラーのようだ。

$ dbt run --profile td
Running with dbt=0.20.0
Found 2 models, 4 tests, 0 snapshots, 0 analyses, 145 macros, 0 operations, 0 seed files, 0 sources, 0 exposures

22:14:14 | Concurrency: 1 threads (target='dev')
22:14:14 |
22:14:14 | 1 of 2 START table model satoshihirose.my_first_dbt_model............ [RUN]
22:14:22 | 1 of 2 OK created table model satoshihirose.my_first_dbt_model....... [OK in 8.54s]
22:14:22 | 2 of 2 START view model satoshihirose.my_second_dbt_model............ [RUN]
22:14:24 | 2 of 2 ERROR creating view model satoshihirose.my_second_dbt_model... [ERROR in 1.47s]
22:14:24 |
22:14:24 | Finished running 1 table model, 1 view model in 16.26s.

Completed with 1 error and 0 warnings:

Runtime Error in model my_second_dbt_model (models/example/my_second_dbt_model.sql)
  PrestoUserError(type=USER_ERROR, name=NOT_SUPPORTED, message="This connector does not support creating views", query_id=20210727_131423_32607_s2qyv)

Done. PASS=1 WARN=0 ERROR=1 SKIP=0 TOTAL=2

TD は View をサポートしていないため、View ではなくテーブルを作成するように設定を変更する。

dbt_project.yml の materialized の箇所を view から table に書き換える。

models:
  my_new_project:
      # Applies to all files under models/example/
      example:
          materialized: table

dbt run の実行に成功した。

dbt run --profile td
Running with dbt=0.20.0
Found 2 models, 4 tests, 0 snapshots, 0 analyses, 145 macros, 0 operations, 0 seed files, 0 sources, 0 exposures

22:17:24 | Concurrency: 1 threads (target='dev')
22:17:24 |
22:17:24 | 1 of 2 START table model satoshihirose.my_first_dbt_model............ [RUN]
22:17:33 | 1 of 2 OK created table model satoshihirose.my_first_dbt_model....... [OK in 8.63s]
22:17:33 | 2 of 2 START table model satoshihirose.my_second_dbt_model........... [RUN]
22:17:40 | 2 of 2 OK created table model satoshihirose.my_second_dbt_model...... [OK in 7.42s]
22:17:40 |
22:17:40 | Finished running 2 table models in 27.49s.

Completed successfully

Done. PASS=2 WARN=0 ERROR=0 SKIP=0 TOTAL=2

コンソールを確認すると、サンプルのテーブルが作成されていることがわかる。

二つのテーブルが作成された。 f:id:wonderthinkanswer:20210727221846p:plain テーブルに追加されたデータ。 f:id:wonderthinkanswer:20210727221933p:plain

結果としては dbt-presto の修正が必要そうで現状のままでは動作しないことが確認できた。

修正が必要な箇所は

  1. http 接続がハードコードされている箇所
  2. start transaction が実行される箇所

1 は新しいモードを追加することで簡単に修正できそうである。2 については、設定などで start transaction の実行を回避できないか調査していたが、dbt 本体にも実行を指定している箇所があるなど簡単な修正では対応できないように感じた。果たして dbt-presto に Treasure Data に合うようなモードを追加するのが良いか、 dbt-athena のように別なプラグインとして提供するのが良いか。