MDSのHeatWave機能を使ってみた
こんにちは。Oracle Cloud Infrastructure(OCI)特集 編集部です。
以前にMySQL Database Service (MDS)を使用したブログを記載していました。
MySQL Database Service (MDS)を使ってみた
そのMDSにおいて、HeatWaveという機能を有効化すると
SQLクエリを高速化できるとの事で、
今回はそのHeatWave機能を実際に使ってみたいと思います。
また、HeatWaveを使用するには条件もあるみたいです。
・HeatWaveを使用可能なMDSのシェイプはあらかじめ決まっている
※現状では
・BM.Standard.E2.64
・MySQL.HeatWave.VM.Standard.E3
・サポートされていないデータ型がある
※その型を除外してロードすることは可能
■参考サイト
・HeatWaveチュートリアル
https://oracle-japan.github.io/ocitutorials/beginners/creating-HeatWave/
・OCIマニュアル(英語)
https://docs.oracle.com/en-us/iaas/mysql-database/doc/heatwave1.html
⇒大まかな内容のため、詳細は下記を参照
・HeatWaveユーザガイド(英語)
https://dev.mysql.com/doc/heatwave/en/
⇒詳細な使用方法はこちらに記載されています
■今回の作業の流れ
・前準備
・1.HeatWave機能の有効化
・2.HeatWave使用準備
・3.検証
前準備
まずはMDSをシェイプ「MySQL.HeatWave.VM.Standard.E3」で作成します。
※MDSの作成方法は以前のブログを参照ください。
MySQL Database Service (MDS)を使ってみた
今回のHeatWaveの検証にあたり、DBのデータ量は多めに用意しようと思いました。
そこで、色々探したところAWSのオープンデータに
大量のテキストデータが存在したため、こちらを使ってみます。
https://registry.opendata.aws/gdelt/
⇒世界各国で発生したイベントのデータベース情報のようです。
AWS CLIを使用してテキストデータをダウンロードし、
“LOAD DATA LOCAL INFILE ~” 文でMDSへ下記のように取り込みました。
データベース名:test_db
テーブル名:test_table
※テーブルの実サイズは 約226GB、レコード数は5億9千万ぐらいでした
1.HeatWave機能の有効化
まずはMDSに対して HeatWave機能の有効化を行うにあたり、
OCI Webコンソールにログインし、
HeatWave機能を有効にしたいMDSの画面を開きます。
画面左下の「HeatWave」をクリックし、
画面右側の「HeatWaveクラスタの追加」を押下します。
※画面に記載の通り、MDSのシェイプは「MySQL.HeatWave.VM.Standard.E3」です
「ノード数」の箇所でSQLクエリを並列実行するサーバ数(HeatWaveクラスタノード数)を
入力するのですが、まずは「ノード数の見積り」ボタンを押下します。
MDS上の実際のデータが読み込まれて表示されるようです。
「∨」をクリックします。
※MDS上に作成した データベース(test_db)とテーブル(test_table)が表示されています。
SQLを高速化したいテーブルにチェックを入れます。
そうすると画面下側にて HeatWaveクラスタノード数が自動的に決定されるため、
この状態で「ノード数見積りの適用」を押下します。
ノード数の情報が追加されています。
この状態で「HeatWaveクラスタの追加」を押下します。
追加が完了すると「アクティブ」と表示されます。
※完了まで約10分でした
2.HeatWave使用準備
mysqlコマンドにてMDSへ接続します。
下記コマンドでHeatWaveが有効であることを確認します。
(「Value」が「ONLINE」であれば有効のようです)
mysql> SHOW STATUS LIKE 'rapid_service_status';
+----------------------+--------+
| Variable_name | Value |
+----------------------+--------+
| rapid_service_status | ONLINE |
+----------------------+--------+
1 row in set (0.01 sec)
mysql>
SQLクエリを高速化したいテーブルに対し、HeatWave (RAPID)を有効にする定義を行います。
mysql> alter table test_db.test_table secondary_engine=rapid;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
テーブルデータをHeatWaveクラスタへ読み込みます。
完了までに13分55秒かかっていました。
※テーブルサイズは約226GBのため、単純計算ですが
277MBytes/secぐらいでデータをロードしている感じですかね。
mysql> alter table test_db.test_table secondary_load;
Query OK, 0 rows affected (13 min 54.45 sec)
mysql>
3.検証
まずはテーブル情報を記載します。
mysql> desc test_table;
+-----------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| GLOBALEVENTID | int | YES | | NULL | |
| SQLDATE | int | YES | | NULL | |
| MonthYear | int | YES | | NULL | |
| Year | int | YES | | NULL | |
| FractionDate | varchar(30) | YES | | NULL | |
| Actor1Code | varchar(30) | YES | | NULL | |
| Actor1Name | text | YES | | NULL | |
| Actor1CountryCode | varchar(30) | YES | | NULL | |
| Actor1KnownGroupCode | varchar(30) | YES | | NULL | |
| Actor1EthnicCode | varchar(30) | YES | | NULL | |
| Actor1Religion1Code | varchar(30) | YES | | NULL | |
| Actor1Religion2Code | varchar(30) | YES | | NULL | |
| Actor1Type1Code | varchar(30) | YES | | NULL | |
| Actor1Type2Code | varchar(30) | YES | | NULL | |
| Actor1Type3Code | varchar(30) | YES | | NULL | |
| Actor2Code | varchar(30) | YES | | NULL | |
| Actor2Name | text | YES | | NULL | |
| Actor2CountryCode | varchar(30) | YES | | NULL | |
| Actor2KnownGroupCode | varchar(30) | YES | | NULL | |
| Actor2EthnicCode | varchar(30) | YES | | NULL | |
| Actor2Religion1Code | varchar(30) | YES | | NULL | |
| Actor2Religion2Code | varchar(30) | YES | | NULL | |
| Actor2Type1Code | varchar(30) | YES | | NULL | |
| Actor2Type2Code | varchar(30) | YES | | NULL | |
| Actor2Type3Code | varchar(30) | YES | | NULL | |
| IsRootEvent | int | YES | | NULL | |
| EventCode | int | YES | | NULL | |
| EventBaseCode | int | YES | | NULL | |
| EventRootCode | int | YES | | NULL | |
| QuadClass | int | YES | | NULL | |
| GoldsteinScale | varchar(30) | YES | | NULL | |
| NumMentions | int | YES | | NULL | |
| NumSources | int | YES | | NULL | |
| NumArticles | int | YES | | NULL | |
| AvgTone | varchar(30) | YES | | NULL | |
| Actor1Geo_Type | int | YES | | NULL | |
| Actor1Geo_FullName | text | YES | | NULL | |
| Actor1Geo_CountryCode | varchar(30) | YES | | NULL | |
| Actor1Geo_ADM1Code | varchar(30) | YES | | NULL | |
| Actor1Geo_Lat | varchar(30) | YES | | NULL | |
| Actor1Geo_Long | varchar(30) | YES | | NULL | |
| Actor1Geo_FeatureID | varchar(30) | YES | | NULL | |
| Actor2Geo_Type | int | YES | | NULL | |
| Actor2Geo_FullName | text | YES | | NULL | |
| Actor2Geo_CountryCode | varchar(30) | YES | | NULL | |
| Actor2Geo_ADM1Code | varchar(30) | YES | | NULL | |
| Actor2Geo_Lat | varchar(30) | YES | | NULL | |
| Actor2Geo_Long | varchar(30) | YES | | NULL | |
| Actor2Geo_FeatureID | varchar(30) | YES | | NULL | |
| ActionGeo_Type | int | YES | | NULL | |
| ActionGeo_FullName | text | YES | | NULL | |
| ActionGeo_CountryCode | varchar(30) | YES | | NULL | |
| ActionGeo_ADM1Code | varchar(30) | YES | | NULL | |
| ActionGeo_Lat | varchar(30) | YES | | NULL | |
| ActionGeo_Long | varchar(30) | YES | | NULL | |
| ActionGeo_FeatureID | varchar(30) | YES | | NULL | |
| DATEADDED | int | YES | | NULL | |
| SOURCEURL | text | YES | | NULL | |
+-----------------------+-------------+------+-----+---------+----------------+
59 rows in set (0.00 sec)
mysql> SELECT table_name, table_rows , floor(data_length/1024/1024/1024) AS table_GB, floor(index_length/1024/1024/1024) AS index_GB
-> FROM information_schema.tables WHERE table_schema='test_db';
+------------+------------+----------+----------+
| TABLE_NAME | TABLE_ROWS | table_GB | index_GB |
+------------+------------+----------+----------+
| test_table | 560800929 | 226 | 0 |
+------------+------------+----------+----------+
1 row in set (0.00 sec)
mysql>
HeatWave無し/有りでの処理速度を比較するにあたり、
次のようにselect文を実行してみました。
・テーブル内を全検索するようなselect文(select count(Year) from test_table;)と
where句で条件をちょっと絞ったselect文(select count(Year) from test_table where Year=2015;)
を実行。「Year」列はint型で西暦が入っています。「2015」は適当です。
(後者のselect文はインデックスも作っていないため、結果的にフルスキャンですが…)
・select文の実行の前にexplainで実行計画を確認しています。
explainにて「type」が「ALL」である事からテーブルのフルスキャンを確認できます。
まずはHeatWaveが無効の状態の結果を記載します。
それぞれの結果は 24分以上かかっていました…。
mysql> explain select count(Year) from test_table;
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------+
| 1 | SIMPLE | test_table | NULL | ALL | NULL | NULL | NULL | NULL | 560800929 | 100.00 | NULL |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------+
1 row in set, 1 warning (0.00 sec)
mysql>
mysql>
mysql> select count(Year) from test_table;
+-------------+
| count(Year) |
+-------------+
| 596867240 |
+-------------+
1 row in set (24 min 24.54 sec)
mysql>
mysql>
mysql> explain select count(Year) from test_table where Year=2015;
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------+
| 1 | SIMPLE | test_table | NULL | ALL | NULL | NULL | NULL | NULL | 560800929 | 10.00 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------+
1 row in set, 1 warning (0.04 sec)
mysql>
mysql>
mysql> select count(Year) from test_table where Year=2015;
+-------------+
| count(Year) |
+-------------+
| 66282411 |
+-------------+
1 row in set (24 min 24.53 sec)
mysql>
次に、HeatWaveが有効の状態の結果です。
explainにて、この時も「type」が「ALL」である事からフルスキャンかと思いますが、
「extra」が「Using secondary engine RAPID」と表示されていることからHeatWaveを使用する事となります。
そして、それぞれの結果は1秒未満で返ってきています。
速すぎですね…。
mysql> explain select count(Year) from test_table;
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+------------------------------+
| 1 | SIMPLE | test_table | NULL | ALL | NULL | NULL | NULL | NULL | 560800929 | 100.00 | Using secondary engine RAPID |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql>
mysql>
mysql>
mysql> select count(Year) from test_table;
+-------------+
| count(Year) |
+-------------+
| 596867240 |
+-------------+
1 row in set (0.18 sec)
mysql>
mysql> explain select count(Year) from test_table where Year=2015;
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------------------------------------+
| 1 | SIMPLE | test_table | NULL | ALL | NULL | NULL | NULL | NULL | 560800929 | 10.00 | Using where; Using secondary engine RAPID |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------------------------------------+
1 row in set, 1 warning (0.00 sec)
mysql>
mysql>
mysql>
mysql> select count(Year) from test_table where Year=2015;
+-------------+
| count(Year) |
+-------------+
| 66282411 |
+-------------+
1 row in set (0.32 sec)
mysql>
HeatWaveが有効な状態で、「Year」列の西暦を「2015」から
「2016」や「2015~2017」に変更してみたりしましたが、
すべて1秒未満で返ってきました。速いです。
mysql> select count(Year) from test_table where Year=2016;
+-------------+
| count(Year) |
+-------------+
| 73269882 |
+-------------+
1 row in set (0.19 sec)
mysql>
mysql> select count(Year) from test_table where Year between 2015 and 2017;
+-------------+
| count(Year) |
+-------------+
| 205821688 |
+-------------+
1 row in set (0.38 sec)
mysql>
停止後に再度SQLを実行すると HeatWaveが無効の時と同じで
24分以上かかっていました。
mysql> explain select count(Year) from test_table;
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------+
| 1 | SIMPLE | test_table | NULL | ALL | NULL | NULL | NULL | NULL | 560800929 | 100.00 | NULL |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------+
1 row in set, 1 warning (0.00 sec)
mysql>
mysql> select count(Year) from test_table;
+-------------+
| count(Year) |
+-------------+
| 596867240 |
+-------------+
1 row in set (24 min 22.65 sec)
mysql>
mysql>
mysql> explain select count(Year) from test_table where Year=2015;
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------+
| 1 | SIMPLE | test_table | NULL | ALL | NULL | NULL | NULL | NULL | 560800929 | 10.00 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+-----------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql>
mysql>
mysql> select count(Year) from test_table where Year=2015;
+-------------+
| count(Year) |
+-------------+
| 66282411 |
+-------------+
1 row in set (24 min 24.57 sec)
mysql>
まとめ
シェイプは「MySQL.HeatWave.VM.Standard.E3」を選択し、
高速化したいテーブルを HeatWaveクラスタへ読み込ませる操作は必要ですが
その他に特別な作業を行わず、SQLクエリがかなり速くなりました!
SQLクエリがどうにも遅くて困っている…という方々には是非使用してほしい機能ですね。
弊社では「MDS/HeatWave」の導入支援を行っておりますので
ご要望・ご相談などございましたらご連絡ください。
▽MySQL Database Service(MDS) / HeatWave導入支援サービス
https://www.techvan.co.jp/solution/it_infra/cloudinfra/mysql_database_service_heatwave/