これは、なにをしたくて書いたもの?
Trinoという分散SQLクエリーエンジンを試してみたいなと思い、まずはインストールしてみたいと思います。
Trino | Distributed SQL query engine for big data
それから、MySQLに接続してTrino経由でアクセスしてみましょう。
Trino
TrinoのWebサイトおよびGitHubリポジトリは、こちらです。
Trino | Distributed SQL query engine for big data
Trinoのドキュメントは、こちら。
Trino documentation — Trino 392 Documentation
Trinoとはなにか?というところですが、これはドキュメントのユースケースのページを見るのが良さそうです。
Use cases — Trino 392 Documentation
Trinoとは、以下のようなものです。
- 分散クエリーを使用して、大量のデータを効率的に扱うように設計されたツール
- HiveやPigなどのMapReduceジョブを使用したHDFSへのクエリーを実行するツールの代替として開発されたが、Trinoがアクセス可能なものはHDFSに限定されない
- RDBMSやApache Cassandraのような、様々な種類のデータソースへのアクセスが可能
データソースへのアクセスには、コネクターと呼ばれるものを使用します。以下がその一覧です。
Connectors — Trino 392 Documentation
また、Trinoは以下のものでは"ありません"。
- RDBMSではなく、MySQLやPostgreSQL、Oracle Databaseなどに代わるものではない
- OLTP向けのツールではない
Trinoに関する用語は、こちらのページに載っています。少しずつ読んでいこうと思います。
Trino concepts — Trino 392 Documentation
こちらも参考に。
高性能分散SQLエンジン「Trino」最速ガイド - NTT Communications Engineers' Blog
ところで、このようなツールの存在はPrestoしか知らなかったのですが、TrinoはPrestoから分かれたもののようです。
Presto | Distributed SQL Query Engine for Big Data
PrestoはFacebookの開発者によって作られたものであり、コアの開発者たちがFacebookを離れて立ち上げたのがTrinoのようです。
Trino | We’re rebranding PrestoSQL as Trino
Trino | Why leaving Facebook/Meta was the best thing we could do for the Trino Community
元のPrestoはPrestoDBと呼び、新しく立ち上げられた方がPrestoSQLと呼ばれた後にTrinoになったようですね。
最初はPrestoを使おうかなと思ったのですが、このTrinoの情勢とJava 17で動作するのはTrinoの方なので、Trinoを試してみようかなと思います。
基本的な考え方は両者とも変わらないようですし。
PrestoがJava 16、17で動作しないというissue。
Error : Building/launching Presto with OpenJDK 16 and 17 · Issue #17438 · prestodb/presto · GitHub
今回は、TrinoをインストールしてMySQLにアクセスしてみたいと思います。
環境
今回の環境は、こちらです。
まずはTrinoを動作させる環境。
$ uname -srrvmpio Linux 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.4 LTS Release: 20.04 Codename: focal
$ java --version openjdk 17.0.4 2022-07-19 OpenJDK Runtime Environment (build 17.0.4+8-Ubuntu-120.04) OpenJDK 64-Bit Server VM (build 17.0.4+8-Ubuntu-120.04, mixed mode, sharing) $ python -V Python 2.7.18
この環境のIPアドレスは、192.168.0.6とします。
また、MySQLについてはこちら。
$ mysql --version mysql Ver 8.0.30 for Linux on x86_64 (MySQL Community Server - GPL)
MySQLは172.17.0.2で動作しているものとし、接続情報はkazuhira/passwordで、practiceというデータベースを作成済みとします。
Trinoをインストールする
それでは、Trinoをインストールしましょう。
こちらのページに沿って進めていきます。
Deploying Trino — Trino 392 Documentation
なお、Dockerイメージを使う方法もありますが、今回はふつうにインストールすることにします。
Trino in containers — Trino 392 Documentation
Trinoのインストール要件は、こちら。
Deploying Trino / Requirements
大まかには、以下です。
- 64 bit Linux
- ulimitsを調整していること
- Java 17.0.3以降
- できればAzul Zulu推奨
- Python 2.6.x、2.7.x、3.xのいずれか
bin/launcherのみで必要
Trinoのインストールは、.tar.gzをダウンロードして
Deploying Trino / Installing Trino
$ curl -LO https://repo1.maven.org/maven2/io/trino/trino-server/392/trino-server-392.tar.gz
展開。
$ tar xf trino-server-392.tar.gz
今回使うTrinoのバージョンは、392ですね。
ディレクトリ内に移動。
$ cd trino-server-392
ディレクトリ構成はこんな感じになっており、コネクターはプラグインとして含まれているようです。
$ tree -d
.
├── bin
│ └── procname
│ ├── Linux-aarch64
│ ├── Linux-ppc64le
│ └── Linux-x86_64
├── lib
└── plugin
├── accumulo
├── atop
├── bigquery
├── blackhole
├── cassandra
├── clickhouse
├── delta-lake
├── druid
├── elasticsearch
├── example-http
├── exchange-filesystem
├── geospatial
├── google-sheets
├── hive
├── http-event-listener
├── iceberg
├── jmx
├── kafka
├── kinesis
├── kudu
├── local-file
├── mariadb
├── memory
├── ml
├── mongodb
├── mysql
├── oracle
├── password-authenticators
├── phoenix5
├── pinot
├── postgresql
├── prometheus
├── raptor-legacy
├── redis
├── redshift
├── resource-group-managers
├── session-property-managers
├── singlestore
├── sqlserver
├── teradata-functions
├── thrift
├── tpcds
└── tpch
50 directories
binディレクトリの中は、こんな感じです。
$ tree bin
bin
├── launcher
├── launcher.properties
├── launcher.py
└── procname
├── Linux-aarch64
│ └── libprocname.so
├── Linux-ppc64le
│ └── libprocname.so
└── Linux-x86_64
└── libprocname.so
4 directories, 6 files
次に、Trinoの設定を行います。
Deploying Trino / Configuring Trino
インストールディレクトリ内に、etcというディレクトリを作成する必要があるようです。
Create an etc directory inside the installation directory.
$ mkdir etc
この中には、以下の設定を含めるようです。
準備行っていきましょう。
ノードの設定。
Deploying Trino / Configuring Trino / Node properties
ノードの設定では、データディレクトリが必要らしく、インストールディレクトリ外に作成することを推奨しているようなので、とりあえず
すぐ上のディレクトリに作成しておきましょう。
$ mkdir ../data
設定は、こんな感じにしました。
etc/node.properties
node.environment=my_trino node.id=340fae6b-55fe-486e-b122-d0fbe61d0ebb node.data-dir=../data
Deploying Trino / Configuring Trino / JVM config
etc/jvm.config
-server -Xmx4G -XX:InitialRAMPercentage=80 -XX:MaxRAMPercentage=80 -XX:G1HeapRegionSize=32M -XX:+ExplicitGCInvokesConcurrent -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -XX:ReservedCodeCacheSize=512M -XX:PerMethodRecompilationCutoff=10000 -XX:PerBytecodeRecompilationCutoff=10000 -Djdk.attach.allowAttachSelf=true -Djdk.nio.maxCachedBufferSize=2000000 -XX:+UnlockDiagnosticVMOptions -XX:+UseAESCTRIntrinsics
概ねドキュメント通りなのですが、ヒープの最大値のみ下げておきました。そんなにたくさんメモリを持った環境で実行していないので。
Trinoの設定。
Deploying Trino / Configuring Trino / Config properties
今回は、コーディネーター兼ワーカーとすることにします。
etc/config.properties
coordinator=true node-scheduler.include-coordinator=true http-server.http.port=8080 discovery.uri=http://192.168.0.6:8080
コーディネーターおよびワーカーについては、こちらに説明があります。
コーディネーターは、ステートメントの解析やクエリーの計画、ワーカーの管理を行うサーバーです。
ワーカーはタスクの実行とデータの処理を行うサーバーです。
今回の設定ではcoordinatorをtrueとしてコーディネーターであるという設定を行い、node-scheduler.include-coordinatorをtrueとすることで
コーディネーター内で作業のスケジューリングを行うことを許可します。
つまり、コーディネーター兼ワーカーです。
テスト目的では両方のサーバーを同居させることもあるようですが、通常の運用だと別個の管理にするみたいですね。
コネクターの設定。
Deploying Trino / Configuring Trino / Catalog properties
etc/catalogディレクトリを作成します。
$ mkdir etc/catalog
このディレクトリ内に、[カタログ名].propertiesでファイルを作成します。内容は、各コネクターのドキュメントを参照します。
MySQLの場合は、こちら。
MySQL connector — Trino 392 Documentation
etc/catalog/mysql.properties
connector.name=mysql connection-url=jdbc:mysql://172.17.0.2:3306 connection-user=kazuhira connection-password=password
コネクターというのは、RDBMSやHiveなどのデータソースに接続するためのドライバーに相当するものです。
Trino concepts / Data sources / Connector
そして、コネクターに関連付けられているのがカタログです。
Trino concepts / Data sources / Catalog
TrinoでSQLステートメントを実行すると、ひとつ以上のカタログに対して実行され、コネクターを介してデータソースに接続します。
ここまでで最低限の準備ができたので、Trinoを起動させます。
Deploying Trino / Running Trino
まずはヘルプを確認。
$ bin/launcher --help
Usage: launcher [options] command
Commands: run, start, stop, restart, kill, status
Options:
-h, --help show this help message and exit
-v, --verbose Run verbosely
--etc-dir=DIR Defaults to INSTALL_PATH/etc
--launcher-config=FILE
Defaults to INSTALL_PATH/bin/launcher.properties
--node-config=FILE Defaults to ETC_DIR/node.properties
--jvm-config=FILE Defaults to ETC_DIR/jvm.config
--config=FILE Defaults to ETC_DIR/config.properties
--log-levels-file=FILE
Defaults to ETC_DIR/log.properties
--data-dir=DIR Defaults to INSTALL_PATH
--pid-file=FILE Defaults to DATA_DIR/var/run/launcher.pid
--launcher-log-file=FILE
Defaults to DATA_DIR/var/log/launcher.log (only in
daemon mode)
--server-log-file=FILE
Defaults to DATA_DIR/var/log/server.log (only in
daemon mode)
-J OPT Set a JVM option
-D NAME=VALUE Set a Java system property
statusコマンドで、Trinoのステータスを確認。
$ bin/launcher status --verbose
config_path = /path/to/trino-server-392/etc/config.properties
data_dir = /path/to/data
etc_dir = /path/to/trino-server-392/etc
install_path = /path/to/trino-server-392
jvm_config = /path/to/trino-server-392/etc/jvm.config
jvm_options = []
launcher_config = /path/to/trino-server-392/bin/launcher.properties
launcher_log = /path/to/data/var/log/launcher.log
log_levels = /path/to/trino-server-392/etc/log.properties
log_levels_set = False
node_config = /path/to/trino-server-392/etc/node.properties
pid_file = /path/to/data/var/run/launcher.pid
properties = {'node.environment': 'my_trino', 'node.data-dir': '../data', 'node.id': '340fae6b-55fe-486e-b122-d0fbe61d0ebb'}
server_log = /path/to/data/var/log/server.log
verbose = True
Not running
Trinoの実行は、startまたはrunで行います。startがデーモン実行で、フォアグラウンドで実行するのがrunですね。
今回は、runで起動してみることにします。
$ bin/launcher run
これで、Trinoが起動しました。
Trino CLIを使ってアクセスしてみる
次に、Trinoにクライアントからアクセスしてみましょう。
Clients — Trino 392 Documentation
Command line interface — Trino 392 Documentation
JDBC driver — Trino 392 Documentation
サードパーティ製のクライアントも含めた一覧は、こちら。
今回はCLIを使うことにします。
Command line interface — Trino 392 Documentation
CLIを使うには、Java 8以上がインストールされていればよいみたいです。
Command line interface / Requirements
また、CLIはTrinoにHTTPまたはHTTPSでのREST APIでアクセスするようです。
インストール。
Command line interface / Installation
$ curl -LO https://repo1.maven.org/maven2/io/trino/trino-cli/392/trino-cli-392-executable.jar
取得したJARファイルをリネームして、実行権限を付与します。
$ mv trino-cli-392-executable.jar trino $ chmod +x trino
バージョンの確認。
$ ./trino --version Trino CLI 392
ヘルプ。
$ ./trino --help
Trino command line interface
USAGE:
trino [-h] [--debug] [--disable-auto-suggestion] [--disable-compression] [--external-authentication] [--ignore-errors] [--insecure]
[--krb5-disable-remote-service-hostname-canonicalization] [--password] [--[no-]progress] [--use-system-truststore] [--version] [--access-token=<token>]
[--catalog=<catalog>] [--client-info=<info>] [--client-request-timeout=<timeout>] [--client-tags=<tags>] [--editing-mode=<editing-mode>] [--execute=<execute>]
[-f=<file>] [--http-proxy=<proxy>] [--keystore-password=<password>] [--keystore-path=<path>] [--keystore-type=<type>] [--krb5-config-path=<path>]
[--krb5-credential-cache-path=<path>] [--krb5-keytab-path=<path>] [--krb5-principal=<principal>] [--krb5-remote-service-name=<name>]
[--krb5-service-principal-pattern=<pattern>] [--network-logging=<level>] [--output-format=<format>] [--schema=<schema>] [--server=<server>] [--session-user=<user>]
[--socks-proxy=<proxy>] [--source=<source>] [--timezone=<timezone>] [--trace-token=<token>] [--truststore-password=<password>] [--truststore-path=<path>]
[--truststore-type=<type>] [--user=<user>] [--external-authentication-redirect-handler=<externalAuthenticationRedirectHandler>]...
[--extra-credential=<credential>]... [--resource-estimate=<estimate>]... [--session=<session>]...
OPTIONS:
--access-token=<token> Access token
--catalog=<catalog> Default catalog
--client-info=<info> Extra information about client making query
--client-request-timeout=<timeout>
Client request timeout (default: 2m)
--client-tags=<tags> Client tags
--debug Enable debug information
--disable-auto-suggestion
Disable auto suggestion
--disable-compression Disable compression of query results
--editing-mode=<editing-mode>
Editing mode [EMACS, VI] (default: EMACS)
--execute=<execute> Execute specified statements and exit
--external-authentication
Enable external authentication
--external-authentication-redirect-handler=<externalAuthenticationRedirectHandler>
External authentication redirect handlers: DESKTOP_OPEN, SYSTEM_OPEN, PRINT, OPEN, ALL (default: ALL)
--extra-credential=<credential>
Extra credentials (property can be used multiple times; format is key=value)
-f, --file=<file> Execute statements from file and exit
-h, --help Show this help message and exit
--http-proxy=<proxy> HTTP proxy to use for server connections
--ignore-errors Continue processing in batch mode when an error occurs (default is to exit immediately)
--insecure Skip validation of HTTP server certificates (should only be used for debugging)
--keystore-password=<password>
Keystore password
--keystore-path=<path> Keystore path
--keystore-type=<type> Keystore type
--krb5-config-path=<path>
Kerberos config file path (default: /etc/krb5.conf)
--krb5-credential-cache-path=<path>
Kerberos credential cache path
--krb5-disable-remote-service-hostname-canonicalization
Disable service hostname canonicalization using the DNS reverse lookup
--krb5-keytab-path=<path>
Kerberos key table path (default: /etc/krb5.keytab)
--krb5-principal=<principal>
Kerberos principal to be used
--krb5-remote-service-name=<name>
Remote peer's kerberos service name
--krb5-service-principal-pattern=<pattern>
Remote kerberos service principal pattern (default: ${SERVICE}@${HOST})
--network-logging=<level>
Network logging level [NONE, BASIC, HEADERS, BODY] (default: NONE)
--output-format=<format>
Output format for batch mode [ALIGNED, VERTICAL, TSV, TSV_HEADER, CSV, CSV_HEADER, CSV_UNQUOTED, CSV_HEADER_UNQUOTED, JSON, NULL] (default:
CSV)
--password Prompt for password
--[no-]progress Show query progress
--resource-estimate=<estimate>
Resource estimate (property can be used multiple times; format is key=value)
--schema=<schema> Default schema
--server=<server> Trino server location (default: localhost:8080)
--session=<session> Session property (property can be used multiple times; format is key=value; use 'SHOW SESSION' to see available properties)
--session-user=<user> Username to impersonate
--socks-proxy=<proxy> SOCKS proxy to use for server connections
--source=<source> Name of source making query (default: trino-cli)
--timezone=<timezone> Session time zone (default: Asia/Tokyo)
--trace-token=<token> Trace token
--truststore-password=<password>
Truststore password
--truststore-path=<path>
Truststore path
--truststore-type=<type>
Truststore type
--use-system-truststore
Use default system (OS) truststore
--user=<user> Username (default: xxxxx)
--version Print version information and exit
では、CLIを使ってTrinoに接続します。
Command line interface / Running the CLI
--serverで接続先のTrinoを指定するのですが、デフォルト値はlocalhost:8080です。
今回はTrinoとCLIを同じサーバー上で動作させているので、以下のいずれでも接続可能です。
$ ./trino $ ./trino --server localhost:8080 $ ./trino --server 192.168.0.6:8080
接続すると、プロンプトが現れます。
trino>
ここで、テーブルにアクセスするには[カタログ名].[スキーマ名(データベース名)].[テーブル名]になるようです。
If the Hive connector is mounted as the hive catalog, and Hive contains a table clicks in database web, that table can be accessed in Trino as hive.web.clicks.
Deploying Trino / Configuring Trino / Catalog properties
MySQL Connectorのドキュメントを見てみましょう。
MySQL connector — Trino 392 Documentation
接続可能なMySQLのバージョンは、5.7、8.0以降のようです。
MySQL connector / Requirements
MySQLのデータ型と、Trinoのデータ型のマッピングはこちら。
MySQL connector / Type mapping
クエリーの例。
MySQL connector / Querying MySQL
使用できるサポートされているSQLは、以下の2つでリストアップされているものに加えて
以下のようです。
INSERTDELETETRUNCATECREATE TABLECREATE TABLE ASDROP TABLECREATE SCHEMADROP SCHEMA
TrinoのSQLに関するドキュメントは、こちら。
SQL language — Trino 392 Documentation
せっかくなので、Trino経由でMySQLにテーブルを作成したりして操作してみましょう。
データベース内のテーブル一覧。
trino> show tables from mysql.practice; Table ------- (0 rows) Query 20220810_151108_00002_qc4ed, FINISHED, 1 node Splits: 7 total, 7 done (100.00%) 1.70 [0 rows, 0B] [0 rows/s, 0B/s]
まだテーブルがないのですが。
テーブルを作成してみましょう。
trino> create table mysql.practice.person(id integer, first_name varchar(255), last_name varchar(255)); CREATE TABLE
CREATE TABLE — Trino 392 Documentation
テーブルができました。
trino> show tables from mysql.practice; Table -------- person (1 row) Query 20220810_151931_00006_qc4ed, FINISHED, 1 node Splits: 7 total, 7 done (100.00%) 0.54 [1 rows, 24B] [1 rows/s, 45B/s]
データを登録してみます。
trino> insert into mysql.practice.person(id, first_name, last_name) values(1, 'カツオ', '磯野'); INSERT: 1 row Query 20220810_152128_00007_qc4ed, FINISHED, 1 node Splits: 11 total, 11 done (100.00%) 0.95 [0 rows, 0B] [0 rows/s, 0B/s] trino> insert into mysql.practice.person(id, first_name, last_name) values(2, 'ワカメ', '磯野'); INSERT: 1 row Query 20220810_152152_00008_qc4ed, FINISHED, 1 node Splits: 11 total, 11 done (100.00%) 0.71 [0 rows, 0B] [0 rows/s, 0B/s] trino> insert into mysql.practice.person(id, first_name, last_name) values(3, 'タラオ', 'フグ田'); INSERT: 1 row Query 20220810_152242_00009_qc4ed, FINISHED, 1 node Splits: 11 total, 11 done (100.00%) 0.52 [0 rows, 0B] [0 rows/s, 0B/s]
INSERT — Trino 392 Documentation
データの取得。
trino> select * from mysql.practice.person order by id; id | first_name | last_name ----+------------+----------- 1 | カツオ | 磯野 2 | ワカメ | 磯野 3 | タラオ | フグ田 (3 rows) Query 20220810_152400_00012_qc4ed, FINISHED, 1 node Splits: 7 total, 7 done (100.00%) 0.21 [3 rows, 0B] [14 rows/s, 0B/s]
SELECT — Trino 392 Documentation
コネクターによってはトランザクションも使えるようなので、試してみましょう。
SQL statement support / Transactions
トランザクションを開始。
trino> start transaction; START TRANSACTION
START TRANSACTION — Trino 392 Documentation
insertを実行してみましょう。
trino> insert into mysql.practice.person(id, first_name, last_name) values(4, 'サザエ', 'フグ田'); Query 20220810_152706_00014_qc4ed failed: Catalog only supports writes using autocommit: mysql
ダメでした。
しかも、このあとselec文も投げられなくなります。
trino> select * from mysql.practice.person order by id; Query 20220810_153307_00021_qc4ed failed: Current transaction is aborted, commands ignored until end of transaction block
trino> rollback; ROLLBACK
ROLLBACK — Trino 392 Documentation
ふつうに登録しましょう…。
trino> insert into mysql.practice.person(id, first_name, last_name) values(4, 'サザエ', 'フグ田'); INSERT: 1 row Query 20220810_153608_00023_qc4ed, FINISHED, 1 node Splits: 11 total, 11 done (100.00%) 0.61 [0 rows, 0B] [0 rows/s, 0B/s] trino> insert into mysql.practice.person(id, first_name, last_name) values(5, 'マスオ', 'フグ田'); INSERT: 1 row Query 20220810_153613_00024_qc4ed, FINISHED, 1 node Splits: 11 total, 11 done (100.00%) 0.54 [0 rows, 0B] [0 rows/s, 0B/s]
確認。
trino> select * from mysql.practice.person order by id; id | first_name | last_name ----+------------+----------- 1 | カツオ | 磯野 2 | ワカメ | 磯野 3 | タラオ | フグ田 4 | サザエ | フグ田 5 | マスオ | フグ田 (5 rows) Query 20220810_153630_00025_qc4ed, FINISHED, 1 node Splits: 7 total, 7 done (100.00%) 0.23 [5 rows, 0B] [22 rows/s, 0B/s]
一応、MySQL側でも確認してみます。
mysql> select * from person order by id; +------+------------+-----------+ | id | first_name | last_name | +------+------------+-----------+ | 1 | カツオ | 磯野 | | 2 | ワカメ | 磯野 | | 3 | タラオ | フグ田 | | 4 | サザエ | フグ田 | | 5 | マスオ | フグ田 | +------+------------+-----------+ 5 rows in set (0.00 sec)
OKですね。
あと、これまでずっと[カタログ名].[スキーマ名(データベース名)].[テーブル名]を付けていましたが、useを使うことで現在の
スキーマ(データベース)を指定できるようなので最後に試してみます。
trino> use mysql.practice; USE
プロンプトが変わります。
trino:practice> use mysql.practice; USE
テーブル名を直接指定してみましょう。
trino:practice> select * from person order by id; id | first_name | last_name ----+------------+----------- 1 | カツオ | 磯野 2 | ワカメ | 磯野 3 | タラオ | フグ田 4 | サザエ | フグ田 5 | マスオ | フグ田 (5 rows) Query 20220810_154405_00029_qc4ed, FINISHED, 1 node Splits: 7 total, 7 done (100.00%) 0.18 [5 rows, 0B] [28 rows/s, 0B/s]
カタログ名もスキーマ名も指定せずにテーブルを解決できましたね。
useは、カタログ名とスキーマ名の両方を指定するか、スキーマ名のみを指定して利用するようです。
trino:practice> use practice; USE
カタログ名を指定せず、スキーマ名のみを指定した場合は、現在のカタログから解決可能なデータベースを選択するようです。
今回は、こんなところにしておきましょう。
まとめ
分散SQLクエリーエンジンである、Trinoを試してみました。
けっこうあっさりと使えて面白いなと思います。これから、いろいろ試してみましょう。