はじめに

みなさん、こんにちは。
Oracle Cloud Infrastructure 検証チームです。

前回に引き続き、OCIの入門編チュートリアルにもある MySQLで高速分析を体験するを実際に検証し、構築してみましたのでご紹介したいと思います。

前回の記事はこちら
XXXX(後日追加)

(前回のおさらい)MySQL HeatWaveとは

MySQL HeatWave(以後HeatWave)は、
MySQL Database Serviceの拡張機能で、検索処理を高速化できるクエリーアクセラレーターです。

今回、構築検証するHeatWaveの構成図は以下のようになります。

HeatWaveには以下のような特徴があります。

  • インメモリで超並列処理を実現し、分析系のSQLも高速に実行できる
  • MySQL 8.0ベースのサービスとなっていますので、今までMySQLで実行していたSQLをそのまま使える
  • オンプレミスや他社クラウド環境のMySQLのデータとシームレスに連携しETL不要かつリアルタイムでデータ同期ができる

作成してみた

改めて手順は下記の通りです。

  1. MDSの作成
    MDSとはOracle MySQL Database Serviceの略です。
    OCI内にデプロイされた完全に管理されたデータベース・サービスで、セキュアなクラウドネイティブ・アプリケーションを迅速にデプロイしようとするオペレータおよび開発者をサポートします。
  2. MySQL HeatWaveノードの構成(HeatWaveノードの追加)
  3. セキュリティリストの修正(イングレス・ルールの追加)
  4. MySQLクライアントのインストール
  5. サンプルデータベースの構築
  6. HeatWaveへのデータのロード
  7. HeatWaveの確認

前回は「3.セキュリティリストの修正(イングレス・ルールの追加)」まで説明しましたので、4.MySQLクライアントのインストール」から説明していきます!

MySQLクライアントのインストール

次は作成したMDSに接続するために、コンピュート・インスタンスMySQLクライアントをインストールしていきます!

  1. 事前に作成したコンピュート・インスタンスに接続し、以下のコマンドを実行します。
    これにより、MySQLチームが提供しているyumの公式リポジトリがセットアップされます。
    sudo yum install https://dev.mysql.com/get/mysql80-community-release-el8-4.noarch.rpm
    
    #実行結果
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    (中略)
    
    Installed:
      mysql80-community-release-el8-4.noarch    
    
    Complete!
  2. 以下のコマンドを実行し、デフォルトの MySQL モジュールの無効化を行ないます。
    sudo yum module disable mysql
    
    #実行結果 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    (中略) 
    Is this ok [y/N]: y
    
    Complete!
  3. 以下のコマンドを実行し、MySQLクライアントをインストールします。
    sudo yum install mysql-community-client
    
    #実行結果 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    (中略) 
    
    Installed:
    mysql-community-client-8.0.33-1.el8.x86_64 mysql-community-client-plugins-8.0.33-1.el8.x86_64
    mysql-community-common-8.0.33-1.el8.x86_64 mysql-community-libs-8.0.33-1.el8.x86_64
    Complete!

これでMySQLクライアントのインストールは完了です!

しっかりとインストールされているか確認してみましょう。

rpm -qa | grep -i mysql

#実行結果 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mysql80-community-release-el8-4.noarch
mysql-community-client-plugins-8.0.33-1.el8.x86_64
mysql-community-common-8.0.33-1.el8.x86_64 
mysql-community-client-8.0.33-1.el8.x86_64 
mysql-community-libs-8.0.33-1.el8.x86_64

「mysql-community-client」が問題なくインストールされていますね!

これでMDSに接続する準備が整いました!

サンプルデータベースの構築

無事、MDSの作成HeatWaveノードの追加、VCNのセキュリティ・リストへイングレスルールの追加インスタンスへMySQLクライアントのインストールが完了しました!

続いて、MDSにサンプルデータベースを構築し、HeatWaveノードへデータをロードしていきます。
サンプルデータベースは事前に準備してあるTPC-H用のデータを使って構築します。

  1. 事前作成済みのコンピュート・インスタンスへ接続し、以下のコマンドを実行しデータをダウンロードします。
    cd /home/opc
    
    wget https://objectstorage.ap-osaka-1.oraclecloud.com/p/seAq8Kgd4TyUqlv5M5qObMJwvsluhCPyOuHOn1L_t4HQYUle2DV-KdFeK44MS7yQ/n/idazzjlcjqzj/b/workshop/o/heatwave_workshop.zip
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    (中略)
    
    2023-06-03 07:07:32 (76.6 MB/s) - ‘heatwave_workshop.zip’ saved [348382849/348382849]
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    
    unzip heatwave_workshop.zip
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    (中略)
    ~~~~~
    inflating: tpch_offload.sql
    inflating: tpch_queries_mysql.sql
    inflating: tpch_queries_rapid.sql
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ll
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    total 340244
    -rw-rw-r--. 1 opc opc 348382849 Oct 23 2021 heatwave_workshop.zip
    drwxr-x---. 2 opc opc 8192 Mar 24 2021 tpch_dump
    -rw-rw-r--. 1 opc opc 3299 Mar 25 2021 tpch_offload.sql
    -rw-rw-r--. 1 opc opc 3497 Jun 11 2021 tpch_queries_mysql.sql
    -rw-rw-r--. 1 opc opc 3496 Jun 11 2021 tpch_queries_rapid.sql
  2. MySQL Shellをインストールします。
    sudo yum install mysql-shell
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    (中略)
    
    Is this ok [y/N]: y
    (中略)
    
    Installed:
    mysql-shell-8.0.33-1.el8.x86_64
    python39-3.9.16-1.module+el8.8.0+21002+9d0e08bf.x86_64
    python39-libs-3.9.16-1.module+el8.8.0+21002+9d0e08bf.x86_64
    python39-pip-20.2.4-7.module+el8.6.0+20625+ee813db2.noarch
    python39-pip-wheel-20.2.4-7.module+el8.6.0+20625+ee813db2.noarch
    python39-setuptools-50.3.2-4.module+el8.5.0+20364+c7fe1181.noarch
    python39-setuptools-wheel-50.3.2-4.module+el8.5.0+20364+c7fe1181.noarch
    
    Complete!
  3. MySQL Shellを使ってMDSに接続します。
    mysqlsh --user=root --password=<管理者ユーザのパスワード> --host=HeatWave.sub06030549381.tutorialvcn.oraclevcn.com --port=3306 --js #--hostの部分は各自のホスト名に変更
    
  4. MySQL Shellのロードダンプユーティリティを使用してMDSにTHP-H用のデータをロードするテストを行ないます。(dryRun: true でテスト実行)
    util.loadDump("/home/opc/tpch_dump", {dryRun: true, resetProgress:true, ignoreVersion:true})
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    Loading DDL and Data from '/home/opc/tpch_dump' using 4 threads.
    (中略)
    
    Starting data load
    Executing common postamble SQL
    0% (0 bytes / 1.11 GB), 0.00 B/s, 8 / 8 tables done
    Recreating indexes - done
    No data loaded.
    0 warnings were reported during the load. ⇒0であることを確認
  5. MySQL Shellのロードダンプユーティリティを使用してMDSにTHP-H用のデータをロードします。
    util.loadDump("/home/opc/tpch_dump", {dryRun: false, resetProgress:true, ignoreVersion:true})
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    Loading DDL and Data from '/home/opc/tpch_dump' using 4 threads.z
    (中略)
    
    Starting data load
    3 thds loading \ 100% (1.11 GB / 1.11 GB), 45.75 MB/s, 8 / 8 tables done
    Recreating indexes - done
    Executing common postamble SQL
    50 chunks (8.66M rows, 1.11 GB) for 8 tables in 1 schemas were loaded in 21 sec (avg throughput 52.84 MB/s)
    0 warnings were reported during the load.
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    \quit
    
  6. mysqlコマンドラインクライアントでMDSに接続し、tpchデータベース内にテーブルが作成されていることを確認します。
    mysql -u root -p -h HeatWave.sub06030549381.tutorialvcn.oraclevcn.com #ホスト名の部分は各自のホスト名に変更 
    Enter password:
    Welcome to the MySQL monitor. Commands end with ; or \g.
    Your MySQL connection id is 53
    Server version: 8.0.33-u3-cloud MySQL Enterprise - Cloud
    
    Copyright (c) 2000, 2023, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> SHOW DATABASES;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | tpch               |
    +--------------------+
    5 rows in set (0.00 sec)
    
    mysql> USE tpch;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    
    mysql> SHOW TABLES;
    +----------------+
    | Tables_in_tpch |
    +----------------+
    | customer       |
    | lineitem       |
    | nation         |
    | orders         |
    | part           |
    | partsupp       |
    | region         |
    | supplier       |
    +----------------+
    8 rows in set (0.00 sec)
  7. 以下のSQLを実行してMDSでの実行時間を確認しておきます。このSQLはTPC-Hベンチマークの1つ目のSQLになります。
    今回は実行に11.33秒の時間がかかりました。
    SELECT
        l_returnflag,
        l_linestatus,
        SUM(l_quantity) AS sum_qty,
        SUM(l_extendedprice) AS sum_base_price,
        SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
        SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
        AVG(l_quantity) AS avg_qty,
        AVG(l_extendedprice) AS avg_price,
        AVG(l_discount) AS avg_disc,
        COUNT(*) AS count_order
    FROM
        lineitem
    WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    GROUP BY l_returnflag , l_linestatus
    ORDER BY l_returnflag , l_linestatus;
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    
    mysql> SELECT
    -> l_returnflag,
    -> l_linestatus,
    -> SUM(l_quantity) AS sum_qty,
    -> SUM(l_extendedprice) AS sum_base_price,
    -> SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    -> SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
    -> AVG(l_quantity) AS avg_qty,
    -> AVG(l_extendedprice) AS avg_price,
    -> AVG(l_discount) AS avg_disc,
    -> COUNT(*) AS count_order
    -> FROM
    -> lineitem
    -> WHERE
    -> l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    -> GROUP BY l_returnflag , l_linestatus
    -> ORDER BY l_returnflag , l_linestatus;
    +--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
    | l_returnflag | l_linestatus | sum_qty     | sum_base_price  | sum_disc_price    | sum_charge          | avg_qty   | avg_price    | avg_disc | count_order |
    +--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
    | A            | F            | 37734107.00 | 56586554400.73  | 53758257134.8700  | 55909065222.827692  | 25.522006 | 38273.129735 | 0.049985 | 1478493     |
    | N            | F            | 991417.00   | 1487504710.38   | 1413082168.0541   | 1469649223.194375   | 25.516472 | 38284.467761 | 0.050093 | 38854       |
    | N            | O            | 74476040.00 | 111701729697.74 | 106118230307.6056 | 110367043872.497010 | 25.502227 | 38249.117989 | 0.049997 | 2920374     |
    | R            | F            | 37719753.00 | 56568041380.90  | 53741292684.6040  | 55889619119.831932  | 25.505794 | 38250.854626 | 0.050009 | 1478870     |
    +--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
    4 rows in set (11.33 sec)

これでMySQL HeatWaveを試す準備が整いました。

以降でHeatWaveへデータをロードし、実際に体験してみましょう

HeatWaveへのデータロード

実際にHeatWaveを使用する時には、事前に対象テーブルのデータをMDSからHeatWaveにロードする必要があります。

HeatWaveにデータをロードした後は、MDSでデータを変更すると自動的に変更が伝搬されるため、この作業は新しくテーブルを作成した時や初回のデータロード時にのみ行う必要があります。

  1. 以下のALTER TABLE文を使い、tpchデータベース内のテーブルに対してSECONDARY_ENGINE=RAPID を定義します。
    ALTER TABLE tpch.customer SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.lineitem SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.nation SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.orders SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.part SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.partsupp SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.region SECONDARY_ENGINE=RAPID;
    ALTER TABLE tpch.supplier SECONDARY_ENGINE=RAPID;
  2. 実行結果
    mysql> ALTER TABLE tpch.customer SECONDARY_ENGINE=RAPID;
    Query OK, 0 rows affected (0.01 sec)
    Records: 0 Duplicates: 0 Warnings: 0
    
    mysql> ALTER TABLE tpch.lineitem SECONDARY_ENGINE=RAPID;
    Query OK, 0 rows affected (0.01 sec)
    Records: 0 Duplicates: 0 Warnings: 0
    
    (以下略)

これにてHeatWaveへのデータのロードが完了しました!

HeatWaveの確認

ついに事前の準備がすべて完了し、HeatWaveを体験することができるようになりました!
先ほど実行したSQLを再度実行して、HeatWaveでの実行時間を確認してみましょう!

  1. SELECT文を再度実行
    SELECT
        l_returnflag,
        l_linestatus,
        SUM(l_quantity) AS sum_qty,
        SUM(l_extendedprice) AS sum_base_price,
        SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
        SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
        AVG(l_quantity) AS avg_qty,
        AVG(l_extendedprice) AS avg_price,
        AVG(l_discount) AS avg_disc,
        COUNT(*) AS count_order
    FROM
        lineitem
    WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    GROUP BY l_returnflag , l_linestatus
    ORDER BY l_returnflag , l_linestatus;
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    
    mysql> SELECT
    -> l_returnflag,
    -> l_linestatus,
    -> SUM(l_quantity) AS sum_qty,
    -> SUM(l_extendedprice) AS sum_base_price,
    -> SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    -> SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
    -> AVG(l_quantity) AS avg_qty,
    -> AVG(l_extendedprice) AS avg_price,
    -> AVG(l_discount) AS avg_disc,
    -> COUNT(*) AS count_order
    -> FROM
    -> lineitem
    -> WHERE
    -> l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    -> GROUP BY l_returnflag , l_linestatus
    -> ORDER BY l_returnflag , l_linestatus;
    +--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
    | l_returnflag | l_linestatus | sum_qty     | sum_base_price  | sum_disc_price    | sum_charge          | avg_qty   | avg_price    | avg_disc | count_order |
    +--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
    | A            | F            | 37734107.00 | 56586554400.73  | 53758257134.8700  | 55909065222.827692  | 25.522005 | 38273.129734 | 0.049985 | 1478493     |
    | N            | F            | 991417.00   | 1487504710.38   | 1413082168.0541   | 1469649223.194375   | 25.516471 | 38284.467760 | 0.050093 | 38854       |
    | N            | O            | 74476040.00 | 111701729697.74 | 106118230307.6056 | 110367043872.497010 | 25.502226 | 38249.117988 | 0.049996 | 2920374     |
    | R            | F            | 37719753.00 | 56568041380.90  | 53741292684.6040  | 55889619119.831932  | 25.505793 | 38250.854626 | 0.050009 | 1478870     |
    +--------------+--------------+-------------+-----------------+-------------------+---------------------+-----------+--------------+----------+-------------+
    4 rows in set (0.17 sec)

    実行時間はなんと0.17秒でした!
    前回実行時は11.33秒だったので、約10秒以上早く結果が返ってきております!

    とても早くなっているのがわかりますね!

  2. 実行計画の確認
    EXPLAINをSELECTの前に付けて実行計画を確認します。
    EXPLAIN SELECT
        l_returnflag,
        l_linestatus,
        SUM(l_quantity) AS sum_qty,
        SUM(l_extendedprice) AS sum_base_price,
        SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
        SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
        AVG(l_quantity) AS avg_qty,
        AVG(l_extendedprice) AS avg_price,
        AVG(l_discount) AS avg_disc,
        COUNT(*) AS count_order
    FROM
        lineitem
    WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    GROUP BY l_returnflag , l_linestatus
    ORDER BY l_returnflag , l_linestatus;
    
    #実行結果 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    
    mysql> EXPLAIN SELECT
    -> l_returnflag,
    -> l_linestatus,
    -> SUM(l_quantity) AS sum_qty,
    -> SUM(l_extendedprice) AS sum_base_price,
    -> SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    -> SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
    -> AVG(l_quantity) AS avg_qty,
    -> AVG(l_extendedprice) AS avg_price,
    -> AVG(l_discount) AS avg_disc,
    -> COUNT(*) AS count_order
    -> FROM
    -> lineitem
    -> WHERE
    -> l_shipdate <= DATE '1998-12-01' - INTERVAL '90' DAY
    -> GROUP BY l_returnflag , l_linestatus
    -> ORDER BY l_returnflag , l_linestatus;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------------------------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                                                   | 
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------------------------------------------------------+
    | 1  | NONE        | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL | NULL     | Using secondary engine RAPID. Use EXPLAIN FORMAT=TREE to show the plan. |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------------------------------------------------------------------+
    1 row in set, 1 warning (0.03 sec)

    HeatWaveを使用する場合は Extra列 に Using secondary engine RAPID と表示されます。

これにてMySQL HeatWaveの検証作業は終了です
お疲れ様でした!

おわりに

今回は、OCIの入門編チュートリアルにある、MySQLで高速分析を体験する を実際に検証し、作成してみました。

いかかでしたでしょうか。

今回の検証では11.33秒から0.17秒へと約66倍もの高速化が実現しました。
これをご覧の皆さまも是非検証して高速化を実感いただきたいです!

最後までご覧いただきありがとうございました!

Oracle Cloudをご検討の際は当社までお気軽にお問い合わせください。