0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MySQL 8.4 のまま分析クエリを速くする — ShannonBase を Docker で試す

0
Posted at

筆者は ShannonBase の開発者です。実際に手を動かして試せる内容にしていますが、そのつもりでお読みください。

この記事の対象

  • MySQL で GROUP BY を含む集計クエリが遅くて困っている
  • 分析用に ClickHouse や BigQuery へ流す構成を検討しているが、二重運用は避けたい
  • とりあえず 15 分で挙動を確かめたい

ShannonBase とは

MySQL 8.4 互換の HTAP データベースです。MySQL 本体の Secondary Engine の仕組みを使って、列指向エンジン(Rapid/IMCS)を同一インスタンス内に持ちます。

大事なのはアプリ側の変更が要らないことです。接続先も、SQL も、コネクタもそのまま。テーブル単位で列指向のミラーを作るかどうかを ALTER で指定するだけです。

1. 起動する

docker run -d \
  --name shannonbase \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=yourpassword \
  shannondata/shannonbase:latest

接続は普通の MySQL クライアントで行けます。

mysql -h 127.0.0.1 -P 3306 -u root -p
SELECT VERSION();
-- 8.4.x

バージョン文字列が 8.4 系で返ります。ここが独自バージョンになっていないのは意図的で、既存のツールチェーン(マイグレーションツール、監視エージェント、ORM のバージョン判定)をそのまま通すためです。

2. データを入れる

TPC-H の lineitem を使うのが手軽です。ここでは簡略版のテーブルで説明します。

CREATE DATABASE bench;
USE bench;

CREATE TABLE orders (
  o_orderkey    BIGINT PRIMARY KEY,
  o_custkey     BIGINT NOT NULL,
  o_orderstatus CHAR(1) NOT NULL,
  o_totalprice  DECIMAL(15,2) NOT NULL,
  o_orderdate   DATE NOT NULL,
  o_orderpriority VARCHAR(15) NOT NULL,
  KEY idx_date (o_orderdate)
) ENGINE=InnoDB;

データ投入は【要記入:データ生成手順 or サンプルダンプの URL】を参照してください。以下は 1,000 万行を入れた前提で進めます。

3. まず InnoDB のまま測る

SET SESSION use_secondary_engine = OFF;

SELECT o_orderpriority, COUNT(*), SUM(o_totalprice)
FROM orders
WHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31'
GROUP BY o_orderpriority;

実行計画を見ておきます。

EXPLAIN FORMAT=TREE
SELECT o_orderpriority, COUNT(*), SUM(o_totalprice)
FROM orders
WHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31'
GROUP BY o_orderpriority;

インデックスレンジスキャン+グルーピングになっているはずです。

4. 列指向ミラーを作る

ALTER TABLE orders SECONDARY_ENGINE = rapid;
ALTER TABLE orders SECONDARY_LOAD;

SECONDARY_LOAD はテーブル全体を列形式に変換してメモリに載せる処理なので、行数に応じて時間がかかります。完了後、ロード状況はこう確認します。

SELECT * FROM performance_schema.rpd_tables;

ロード後は、InnoDB 側への INSERT/UPDATE/DELETE が列側に自動で同期されます。バッチ再ロードは不要です。内部的には Redo Log と DML 通知の二重チャネルで追従しています。

5. もう一度測る

SET SESSION use_secondary_engine = ON;

EXPLAIN FORMAT=TREE
SELECT o_orderpriority, COUNT(*), SUM(o_totalprice)
FROM orders
WHERE o_orderdate BETWEEN '1995-01-01' AND '1995-12-31'
GROUP BY o_orderpriority;

実行計画に副エンジンへのオフロードが現れれば成功です。同じ SQL、同じ接続、同じアプリケーションコードのまま実行経路だけが変わります。

計測結果の例(【要記入:実測値。マシンスペックと my.cnf を必ず併記】)

クエリ InnoDB Rapid
上記の集計 【要記入】 【要記入】

オフロードされない場合、クエリは自動的に InnoDB にフォールバックします。結果は常に正しいですが、速度は出ません。EXPLAIN でオフロードの有無を確認するのが確実です。

6. ハマりどころ

メモリ不足で SECONDARY_LOAD が失敗する
列側は全量メモリ常駐です。テーブルサイズに対して十分な割り当てが必要です。まず一番重い 1 テーブルだけをロードして様子を見るのが安全です。

オフロードされない
すべての演算子が対応しているわけではありません。ウィンドウ関数や一部のサブクエリ形は InnoDB 側に落ちます。EXPLAIN FORMAT=TREE で確認してください。

行と列で結果が違う
あってはならない状態です。もし遭遇したら再現 SQL とスキーマを添えて Issue を立ててもらえると非常に助かります。行実行と列実行の意味論一致は最優先で扱っています。

現時点の制約

正直に書いておきます。

  • 列指向側はメモリ常駐前提のため、データサイズはメモリ量に律速されます
  • ネイティブな ANN ベクトルインデックスはありません。MySQL コミュニティ本体のベクトルインデックス実装を待つ方針です
  • オフロード非対応の演算子があります

まとめ

MySQL 8.4 互換のまま、ALTER TABLE 2 行で列指向の分析経路が足せます。CDC パイプラインとスキーマの二重管理が要らない点が、既存の分析基盤構成に対する主な差分です。

リポジトリ: https://github.com/Shannon-Data/ShannonBase


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?