209 Views
May 07, 25
スライド概要
【講演内容】
HeatWave Lakehouse でオブジェクト・ストレージのデータ変換/加工ができるか試してみました!
- HeatWaveの魅力とは?
‐ HeatWave Lakehouse / Lakehouse Architecture
‐ HeatWaveでクエリ結果
をオブジェクトストレージにエクスポート → 書いた結果をオブジェクトストレージにエクスポート、これをOCIのためみてみます。
【発表者】
@vidaisuki 氏
【イベント情報】
HeatWavejp Meetup #13
https://heatwavejp.connpass.com/even/349599/
HeatWavejpは、MySQL HeatWave の良さを知っていただき、参加者同士でノウハウやナレッジを共有できるユーザーコミュニティです。参加者同士のつながりを深めるため、以下の活動を行ってまいります。 COMMUNICATION *Slackやconnpassを活用したユーザー同士のコミュニケーションの場の提供 EVENT *オンライン/オフラインでのMeetupセミナーや勉強会の開催(隔月程度) SHARING *製品情報や最新アップデート、リリース情報の共有 INTERACT *参加者のコミュニティ・ネットワークやユーザー同士の交流を促進
HeatWave Lakehouse で オブジェクト・ストレー ジのデータ変換/加工がで きるか試してみた! 2025/04/17 HeatWavejp Meetup #13 @vidaisuki 2025
自己紹介 • @vidaisuki • 都内某企業でDBA • MySQLは5.7以降ごぶさたなので優しく願います。
HeatWavejp 2周年おめでとうございます!
HeatWaveの魅力とは? 魅力ポイント 内容・補足 爆速な分析 インメモリ列指向エンジン(HeatWave)で、100 倍以上のクエリ高速化も可能 MySQLに統合 別のDWHを用意せず、MySQLのままでOLAPが できる(ETL不要!) マネージド & 自動化 OCI上で完全マネージド。スケーリングやイン デックス最適化(Autopilot)も自動 Lakehouse対応(2023〜) Parquet/CSVファイルを直接分析可能。S3やOCI Object StorageをそのままJOINできる コスト効率が高い SnowflakeやRedshiftと比べて最大80%以上安く、 かつ高速(公式ベンチあり) Oracle製MySQLなので安心 MySQLの作者がOracleにいる安心感。エンタープ ライズ対応も手厚い 使い慣れたSQLで全部できる 別言語やツールを覚えずに、SQLだけで分析〜可 視化までできるのが強み ここが一番の魅力かなと思いますが、MySQLを使っていないと縁が遠い
HeatWave Lakehouse クラウドを使っているとオブジェクトストレージにデータが溜まっていきがちなので、個人的にはこちら に期待
Lakehouse Architecture Data source Data File Prepare and transform Silver Layer Bronze Layer Analyze Gold Layer BI Tool Transform Tool Database Events Functions Integration データの加工/変換が必要 Analytics Engine
Exporting query results to object storage with HeatWave • クエリの結果をオブジェクトストレージにエクスポート、これを OCIでためしてみます。 • Changes in HeatWave 9.1.1 (2024-11-19, General Availability) • HeatWave Lakehouse • HeatWave Lakehouse now supports exporting query results directly to an object store in OCI or AWS. This lets you store, transform, and persist data in CSV and Parquet formats. The new syntaxes introduced make it easier to export data, especially in command-line environments, and provide more control over the output format. This enhancement enables efficient data storage, retrieval, and transformation, improving data management and analysis workflows. • For more information, see Exporting Query Results to Object Storage. (WL #16214)
参考記事 • https://blogs.oracle.com/mysql/post/exporting-queryresults-to-object-storage-with-heatwave
DBシステム作成 Heatwaveレイクハウスを有効に(デフォルトで有効)。 9.0以降で追加された機能検証なので、9系の最新版(今回(2025/04/17)は9.2.2)で作成。 Production,Development,Always Freeの選択はどれでも可。
権限の確認(MySQL) EXPORT_QUERY_RESULTS が付与されている事 初期ユーザー(Admin)では最初からついているが、ユーザーを作成する場合 は別途付与する。 SQL > show grants; -略 | GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE,zenn REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE ROLE, DROP ROLE ON *.* TO `vidaisuki`@`%` WITH GRANT OPTION | | GRANT APPLICATION_PASSWORD_ADMIN,AUDIT_ADMIN,BACKUP_ADMIN,CONNECTION_ADMIN,EXPORT_QUERY_RESULTS,FLUSH_OPTIMIZER _COSTS,FLUSH_PRIVILEGES,FLUSH_STATUS,FLUSH_TABLES,FLUSH_USER_RESOURCES,OPTION_TRACKER_OBSERVER,REPLICATIO N_APPLIER,ROLE_ADMIN,SET_ANY_DEFINER,SHOW_ROUTINE,TRANSACTION_GTID_TAG,VECTOR_STORE_LOAD_EXEC,XA_RECOVER_ ADMIN ON *.* TO `vidaisuki`@`%` WITH GRANT OPTION | 略|
サンプルデータ(TPC-H) http://www.tpc.org/tpch/ dbgenでデータ作成 区切り文字「|」、行末「|¥¥n」 $ head -5 orders.tbl 1|36901|O|173665.47|1996-01-02|5-LOW|Clerk#000000951|0|nstructions sleep furiously among | 2|78002|O|46929.18|1996-12-01|1-URGENT|Clerk#000000880|0| foxes. pending accounts at the pending, silent asymptot| 3|123314|F|193846.25|1993-10-14|5-LOW|Clerk#000000955|0|sly final accounts boost. carefully regular ideas cajole carefully. depos| 4|136777|O|32151.78|1995-10-11|5-LOW|Clerk#000000124|0|sits. slyly regular warthogs cajole. regular, regular theodolites acro| 5|44485|F|144659.20|1994-07-30|5-LOW|Clerk#000000925|0|quickly. bold deposits sleep slyly. packages use slyly|
権限の確認(OCI) 動的グループの作成
• アイデンティティ>ドメイン>”ドメイン名”>動的グループ
• 動的グループの作成>一致ルールの追加
• ALL{resource.type='mysqldbsystem',
resource.compartment.id = '<user-Compartment-ocid>'}
• ALL {instance.compartment.id = ‘<user-Compartmentocid>’} ※コンピュートインスタンスからオブジェクトストレージにアクセスする為
権限の確認(OCI) ポリシーの作成
• アイデンティティ>ポリシー>ポリシーの作成
• >ポリシーステートメントの編集
• Allow dynamic-group '<Domain-name>'/'<Dynamic-Group-Name>' to read buckets in
compartment id <user-Compartment-ocid>
• Allow dynamic-group '<Domain-name>'/'<Dynamic-Group-Name>' to manage objects in
compartment id <user-Compartment-ocid> where any
{request.permission='OBJECT_READ',request.permission='OBJECT_CREATE',
request.permission='OBJECT_INSPECT', request.permission='OBJECT_OVERWRITE',
request.permission='OBJECT_DELETE’}
• 前項で作成した動的グループにオブジェクトストレージへのアクセスを
許可
バケットの準備 テーブルごとにフォル ダを作っておくと、 テーブル作成時に Prefixで指定できる ので具合がよい。
ファイルアップロード コンピュートインスタンスからファイルアップロード(もしくは直接バケットにアップロード)。 $ oci os object put --bucket-name heatwave-lakehouse-test -name "lakehouse_test/nation/orders.tbl" -file ./orders.tbl -auth instance_principal
テーブル作成
バケットやdialect(ファイルの書式等)を指定
CREATE TABLE `ORDERS` (
`O_ORDERKEY` bigint NOT NULL,
`O_CUSTKEY` int NOT NULL,
`O_ORDERSTATUS` char(1) NOT NULL,
`O_TOTALPRICE` decimal(15,2) NOT NULL,
`O_ORDERDATE` date NOT NULL,
`O_ORDERPRIORITY` char(15) NOT NULL,
`O_CLERK` char(15) NOT NULL,
`O_SHIPPRIORITY` int NOT NULL,
`O_COMMENT` varchar(79) NOT NULL) ENGINE=Lakehouse DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci SECONDARY_ENGINE=RAPID ENGINE_ATTRIBUTE='{"file":
[{"bucket": "heatwave-lakehouse-test",
"prefix": "lakehouse_test/orders/",
"region": "ap-tokyo-1", "namespace": "bucket_namespace"}],
"dialect": {"format": "csv", "has_header": false, "is_strict_mode": false,
"field_delimiter": "|", "record_delimiter": "|¥¥n"}}'
データをHeatWaveにロード
SQL > SET @input_list = '[{
"db_name":
"lakehouse_test",
"tables":
[
{
"table_name": "ORDERS"
}
] }]';
SQL > SET @options = JSON_OBJECT('mode', 'normal',
'refresh_external_tables', TRUE);
SQL > CALL sys.heatwave_load(CAST(@input_list AS JSON),
@options);
データをHeatWaveにロードを確認
Prefix指定だとWarningが出るが・・、(name指定だと出ない)
SQL > SELECT log FROM sys.heatwave_autopilot_report WHERE type IN ('error',
'warn');
+----------------------------------------------------------------------------------------------| {"cmd": "¥"ALTER TABLE /*+ AUTOPILOT_DISABLE_CHECK */
`lakehouse_test`.`ORDERS` SECONDARY_LOAD;¥"", "msg": "Command Issue", "warn":
"[WARNINGS SUMMARY] Lakehouse Load had 1 warning(s) out of which 1 were not
recorded (due to max_error_count limit or filtering rules)", "location":
"EXECUTE stmt", "table_name": "ORDERS", "schema_name": "lakehouse_test"} |
| {"cmd": "¥"ALTER TABLE /*+ AUTOPILOT_DISABLE_CHECK */
`lakehouse_test`.`ORDERS` SECONDARY_LOAD;¥"", "msg": "Command Issue", "warn":
"[WARNINGS SUMMARY] 1 warning(s) with code: 6069(ER_LH_EMPTY_FILE)",
"location": "EXECUTE stmt", "table_name": "ORDERS", "schema_name":
"lakehouse_test"}
データをHeatWaveにロードを確認
DataはLoadできている。
SQL > show table status like 'ORDERS';
+--------+-----------+---------+------------+---------+----------------+-------------+----------------+--------------+-----------+----------------+---------------------+-------------+-----------+--------------------+----------+---------------------------------------------+---------+
| Name
| Engine
| Version | Row_format | Rows
| Avg_row_length | Data_length |
Max_data_length | Index_length | Data_free | Auto_increment | Create_time
| Update_time |
Check_time | Collation
| Checksum | Create_options
|
Comment |
+--------+-----------+---------+------------+---------+----------------+-------------+----------------+--------------+-----------+----------------+---------------------+-------------+-----------+--------------------+----------+---------------------------------------------+---------+
| ORDERS | Lakehouse |
10 | Dynamic
| 1500000 |
0 |
171952161 |
0 |
0 |
0 |
NULL | 2025-04-16 21:39:26 | NULL
| NULL
|
utf8mb4_0900_ai_ci |
NULL | SECONDARY_ENGINE="RAPID" SECONDARY_LOAD="1" |
|
+--------+-----------+---------+------------+---------+----------------+-------------+----------------+--------------+-----------+----------------+---------------------+-------------+-----------+--------------------+----------+---------------------------------------------+---------+
1 row in set (0.0020 sec)
Export用 フォルダを作成 sammary-layerという フォルダを作成
INTO OUTFILE実行
select YEAR(O_ORDERDATE) year,count(*) count from ORDERS WHERE
YEAR(O_ORDERDATE) in ('1993', '1994', '1995') GROUP BY YEAR(O_ORDERDATE)
INTO OUTFILE WITH PARAMETERS '{
"file":
[
{
"region": "ap-tokyo-1",
"namespace": "bucket_namespace",
"bucket": "heatwave-lakehouse-test",
"prefix": "lakehouse_test/summary-layer/"
}
]
, "dialect": {"has_header": true, "format": "csv"}
}';
バケットの状態 INTO OUTFILEで指定したPrefixの配下に自動でフォルダとファイルが配置される(名前は自動生 成)。
再度 INTO OUTFILE実行
select YEAR(O_ORDERDATE) year,count(*) count from ORDERS WHERE
YEAR(O_ORDERDATE) in ('1996', '1997', '1998') GROUP BY YEAR(O_ORDERDATE)
INTO OUTFILE WITH PARAMETERS '{
"file":
[
{
"region": "ap-tokyo-1",
"namespace": "bucket_namespace",
"bucket": "heatwave-lakehouse-test",
"prefix": "lakehouse_test/summary-layer/"
}
]
, "dialect": {"has_header": true, "format": "csv"}
}';
バケットの状態 クエリ実行毎にフォルダが作られる
フォルダの中 $ cat n0-to-c1.csv "year","count" 1993,226645 1994,227597 1995,228637
Exportし
た
ファイル
を元に
Table作成
SQL> SET @input_list = '[
{
"db_name": "lakehouse_test",
"tables": [
"ORDERS_COUNT",
{
"table_name": "ORDERS_COUNT",
"engine_attribute":
{
"dialect": {"format": "csv",
"field_delimiter": ",",
"has_header": true,
"record_delimiter": "¥¥n",
"is_strict_mode": false
},
"file": [{"region": "ap-tokyo-1",
"namespace": "bucket_namespace",
"bucket": "heatwave-lakehouse-test",
"prefix": "lakehouse_test/summary-layer/"
}]
}
}
]
}]';
SQL> SET @options = JSON_OBJECT('mode', 'normal');
SQL> CALL sys.heatwave_load(CAST(@input_list AS JSON), @options);
テーブル作成確認
SQL > SHOW CREATE TABLE 'ORDERS_COUNT'
CREATE TABLE `ORDERS_COUNT` (
`year` year NOT NULL,
`count` mediumint unsigned NOT NULL
) ENGINE=Lakehouse DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
SECONDARY_ENGINE=RAPID /*!80021 ENGINE_ATTRIBUTE='{"file": [{"bucket":
"heatwave-lakehouse-test", "prefix": "lakehouse_test/summary-layer/",
"region": "ap-tokyo-1", "namespace": "bucket_namespace"}], "dialect":
{"format": "csv", "has_header": true, "is_strict_mode": false,
"field_delimiter": ",", "record_delimiter": "¥¥n"}}' */
データ確認 SQL > select * from ORDERS_COUNT ORDER BY year; +------+--------+ | year | count | +------+--------+ | 1993 | 226645 | | 1994 | 227597 | | 1995 | 228637 | | 1996 | 228626 | | 1997 | 227783 | | 1998 | 133623 | +------+--------+ 6 rows in set (0.0067 sec)
余談1 Incremental load Incremental と名付けられていますが、更新・削除も反映します。 更新があったファイルをReloadしている。
Bucketの更新を検知して自動リロード EventsとFunctionsを組み合わせれば(たぶん)実現可能 ファイル追加/更新/削除 File リロード MySQL HeatWave Object Storage イベント通知 コマンド実行 Function起動 Events OCI Functions ※自動ReloadはHeatWave側のロードマップにあるそうです。
余談2 Primary key
• Lakehouse tableでも有効にできますが、初回ロード時しか
チェックが行われないようです?
CREATE TABLE `NATION_PK` (
`N_NATIONKEY` int NOT NULL,
`N_NAME` char(25) NOT NULL,
`N_REGIONKEY` int NOT NULL,
`N_COMMENT` varchar(152) DEFAULT NULL,
PRIMARY KEY (`N_NATIONKEY`)
) ENGINE=Lakehouse DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
SECONDARY_ENGINE=RAPID /*!80021 ENGINE_ATTRIBUTE='{"file": [{"bucket":
"heatwave-lakehouse-test", "prefix": "lakehouse_test/nation/", "region": "aptokyo-1", "namespace": "bucket_namespace"}], "dialect": {"format": "csv",
"has_header": false, "is_strict_mode": true, "field_delimiter": "|",
"record_delimiter": "|¥¥n", "check_constraints": true}}'
Primary key
• 重複ありデータで初回ロード
$ cat nation.tbl
26|HOGE|4|hoge hoge|
26|HOGE|4|hoge hoge|
• エラー
{"cmd": "¥"ALTER TABLE /*+ AUTOPILOT_DISABLE_CHECK */
`lakehouse_test`.`NATION_PK` SECONDARY_LOAD;¥"", "msg": "Command Failed",
"error": "Duplicate entry '26' for key 'NATION_PK.PRIMARY'.", "location":
"EXECUTE stmt",
"table_name": "NATION_PK", "schema_name": "lakehouse_test"}
Primary key • 重複なしで初回ロード $ cat nation.tbl.first 1|FIRST|4|hoge hoge| 26|HOGE|4|hoge hoge| • 2回目は重複ありでロード(これは通る) $ cat nation.tbl.second 26|HOGE|4|hoge hoge| 26|HOGE|4|hoge hoge| • Indexを作るわけではないので、重複排除が必要な場合はソース 側で行う想定
まとめ • Heatwave Lakehouseで基本的なデータ変換/加工は可能。 • INTO OUTFILEの出力先ファイル名が指定できたらなお良い。 • カラムの自動追加などが出来たらさらによい。 • 今回の話とは関係ないがHeatWaveは従量課金では無いので費 用対効果は高いと思われる。ので、 • HeatWaveの今後に期待しております