sql >> データベース >  >> RDS >> MariaDB

Sysbenchを使用してMySQLでシャードテーブルのテストデータを生成する

    Sysbenchは、テストデータを生成し、MySQLOLTPベンチマークを実行するための優れたツールです。通常、Sysbenchを使用してベンチマークを実行する場合は、準備-実行-クリーンアップサイクルを実行します。デフォルトでは、Sysbenchによって生成されるテーブルは、標準の非パーティションベーステーブルです。もちろん、この動作は拡張できますが、LUAスクリプトでの記述方法を知っている必要があります。

    このブログ投稿では、Sysbenchを使用してMySQLでパーティションテーブルのテストデータを生成する方法を紹介します。これは、テーブルのパーティション分割、データ分散、クエリルーティングの因果関係をさらに深く掘り下げるための遊び場として使用できます。

    単一サーバーのテーブルパーティショニング

    単一サーバーのパーティション化とは、単にすべてのテーブルのパーティションが同じMySQLサーバー/インスタンスに存在することを意味します。テーブル構造を作成するときに、すべてのパーティションを一度に定義します。この種のパーティショニングは、時間の経過とともに有用性が失われ、そのデータのみを含む1つまたは複数のパーティションを削除することでパーティションテーブルから簡単に削除できるデータがある場合に適しています。

    Sysbenchスキーマを作成します:

    mysql> CREATE SCHEMA sbtest;

    sysbenchデータベースユーザーを作成します:

    mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
    mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'sbtest'@'%';

    Sysbenchでは、-prepareコマンドを使用して、スキーマ構造を使用してMySQLサーバーを準備し、データの行を生成します。この部分をスキップして、テーブル構造を手動で定義する必要があります。

    パーティションテーブルを作成します。この例では、sbtest1という名前のテーブルを1つだけ作成し、「k」という名前の列で分割します。これは、基本的に0から1,000,000の範囲の整数です(--table-sizeオプションに基づく)。後で挿入のみの操作で使用する予定です):

    mysql> CREATE TABLE `sbtest1` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `k` int(11) NOT NULL DEFAULT '0',
      `c` char(120) NOT NULL DEFAULT '',
      `pad` char(60) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`,`k`)
      )
      PARTITION BY RANGE (k) (
        PARTITION p1 VALUES LESS THAN (499999),
        PARTITION p2 VALUES LESS THAN MAXVALUE
      );

    2つのパーティションを作成します-最初のパーティションはp1と呼ばれ、列「k」の値が499,999未満のデータを格納し、2番目のパーティションp2は残りの値を格納します。また、両方の重要な列を含む主キーを作成します。「id」は行IDを表し、「k」はパーティションキーです。パーティショニングでは、主キーにテーブルのパーティショニング関数(範囲パーティション関数で「k」を使用)のすべての列を含める必要があります。

    パーティションが存在することを確認します:

    mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
           FROM INFORMATION_SCHEMA.PARTITIONS 
           WHERE TABLE_SCHEMA='sbtest2' 
           AND TABLE_NAME='sbtest1';
    +--------------+------------+----------------+------------+
    | TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
    +--------------+------------+----------------+------------+
    | sbtest       | sbtest1    | p1             |          0 |
    | sbtest       | sbtest1    | p2             |          0 |
    +--------------+------------+----------------+------------+

    次に、以下のようにSysbenchの挿入のみの操作を開始できます。

    $ sysbench \
    /usr/share/sysbench/oltp_insert.lua \
    --report-interval=2 \
    --threads=4 \
    --rate=20 \
    --time=9999 \
    --db-driver=mysql \
    --mysql-host=192.168.11.131 \
    --mysql-port=3306 \
    --mysql-user=sbtest \
    --mysql-db=sbtest \
    --mysql-password=passw0rd \
    --tables=1 \
    --table-size=1000000 \
    run

    Sysbenchの実行に伴ってテーブルパーティションが大きくなるのを確認してください:

    mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
           FROM INFORMATION_SCHEMA.PARTITIONS 
           WHERE TABLE_SCHEMA='sbtest2' 
           AND TABLE_NAME='sbtest1';
    +--------------+------------+----------------+------------+
    | TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
    +--------------+------------+----------------+------------+
    | sbtest       | sbtest1    | p1             |       1021 |
    | sbtest       | sbtest1    | p2             |       1644 |
    +--------------+------------+----------------+------------+

    COUNT関数を使用して行の総数をカウントすると、パーティションによって報告された行の総数に対応します。

    mysql> SELECT COUNT(id) FROM sbtest1;
    +-----------+
    | count(id) |
    +-----------+
    |      2665 |
    +-----------+
    以上です。試してみることができる単一サーバーのテーブルパーティショニングの準備ができています。

    マルチサーバーテーブルのパーティション分割

    マルチサーバーパーティショニングでは、次の図に示すように、複数のMySQLサーバーを使用して、特定のテーブル(sbtest1)のデータのサブセットを物理的に格納します。

    2つの独立したMySQLノード(mysql1とmysql2)をデプロイします。 sbtest1テーブルはこれら2つのノードでパーティション化され、このパーティションとホストの組み合わせをシャードと呼びます。 Sysbenchは、アプリケーション層を模倣して、3番目のサーバーでリモートで実行されています。 Sysbenchはパーティションに対応していないため、データベースクエリを適切なシャードにルーティングするためのデータベースドライバーまたはルーターが必要です。この目的を達成するためにProxySQLを使用します。

    この目的のために、sbtest3という別の新しいデータベースを作成しましょう:

    mysql> CREATE SCHEMA sbtest3;
    mysql> USE sbtest3;

    sbtestデータベースユーザーに適切な権限を付与します:

    mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
    mysql> GRANT ALL PRIVILEGES ON sbtest3.* TO 'sbtest'@'%';

    mysql1で、テーブルの最初のパーティションを作成します。

    mysql> CREATE TABLE `sbtest1` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `k` int(11) NOT NULL DEFAULT '0',
      `c` char(120) NOT NULL DEFAULT '',
      `pad` char(60) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`,`k`)
      )
      PARTITION BY RANGE (k) (
        PARTITION p1 VALUES LESS THAN (499999)
      );

    スタンドアロンパーティショニングとは異なり、0〜499,999の範囲の列「k」値を持つすべての行を格納するためにテーブルにパーティションp1の条件を定義するだけです。

    mysql2で、別のパーティションテーブルを作成します:

    mysql> CREATE TABLE `sbtest1` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `k` int(11) NOT NULL DEFAULT '0',
      `c` char(120) NOT NULL DEFAULT '',
      `pad` char(60) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`,`k`)
      )
      PARTITION BY RANGE (k) (
        PARTITION p2 VALUES LESS THAN MAXVALUE
      );

    2番目のサーバーでは、列 "k"の予想値の残りを格納することにより、2番目のパーティションのデータを保持する必要があります。

    これで、テーブル構造にテストデータを入力する準備が整いました。

    Sysbenchの挿入専用操作を実行する前に、ProxySQLサーバーをクエリルーターとしてインストールし、MySQLシャードのゲートウェイとして機能させる必要があります。マルチサーバーシャ​​ーディングでは、アプリケーションからのデータベース接続を正しいシャードにルーティングする必要があります。そうしないと、次のエラーが表示されます。

    1526 (Table has no partition for value 503599)

    ClusterControlを使用してProxySQLをインストールし、sbtestデータベースユーザーをProxySQLに追加し、両方のMySQLサーバーをProxySQLに追加し、mysql1をホストグループ11として、mysql2をホストグループ12として構成します。

    次に、クエリのルーティング方法に取り組む必要があります。 Sysbenchによって実行されるINSERTクエリのサンプルは、次のようになります。

    INSERT INTO sbtest1 (id, k, c, pad) 
      VALUES (0, 503502, '88816935247-23939908973-66486617366-05744537902-39238746973-63226063145-55370375476-52424898049-93208870738-99260097520', '36669559817-75903498871-26800752374-15613997245-76119597989')

    したがって、次の正規表現を使用して、「k」=> 500000のINSERTクエリをフィルタリングし、パーティショニング条件を満たすようにします。

    ^INSERT INTO sbtest1 \(id, k, c, pad\) VALUES \([0-9]\d*, ([5-9]{1,}[0-9]{5}|[1-9]{1,}[0-9]{6,}).*

    上記の式は、単に以下をフィルタリングしようとします:

    • [0-9] \ d * -ここでは自動インクリメント整数を期待しているため、任意の整数と照合します。

    • [5-9] {1、} [0-9] {5} -値は、最初の桁が5の整数、最後の5桁が0〜9の整数に一致し、500,000〜999,999の範囲の値に一致します。

    • [1-9] {1、} [0-9] {6、} -値は、最初の桁が1〜9の整数に一致し、最後の6桁以上が0〜9の整数に一致して、1,000,000以上の値に一致します。

    2つの同様のクエリルールを作成します。最初のクエリルールは、上記の正規表現の否定です。このルールID51を指定し、宛先ホストグループは列 "k" <500,000に一致し、クエリを最初のパーティションに転送するためにホストグループ11である必要があります。次のようになります:

    上のスクリーンショットの「NegateMatchPattern」に注意してください。このオプションは、このクエリルールを適切にルーティングするために重要です。

    次に、同じ正規表現を使用して、ルールID 52で別のクエリルールを作成します。宛先ホストグループは12である必要がありますが、今回は、以下に示すように、[NegateMatchPattern]をfalseのままにします。

    次に、Sysbenchを使用して挿入のみの操作を開始し、テストデータを生成できます。 。 MySQLアクセス関連の情報は、ProxySQLホスト(ポート6033の192.168.11.130)である必要があります:

    $ sysbench \
    /usr/share/sysbench/oltp_insert.lua \
    --report-interval=2 \
    --threads=4 \
    --rate=20 \
    --time=9999 \
    --db-driver=mysql \
    --mysql-host=192.168.11.130 \
    --mysql-port=6033 \
    --mysql-user=sbtest \
    --mysql-db=sbtest3 \
    --mysql-password=passw0rd \
    --tables=1 \
    --table-size=1000000 \
    run

    エラーが表示されない場合は、ProxySQLがクエリを正しいシャード/パーティションにルーティングしたことを意味します。 Sysbenchプロセスの実行中に、クエリルールのヒット数が増加していることがわかります。

    [上位のクエリ]セクションで、クエリルーティングの概要を確認できます。

    再確認するには、mysql1にログインして最初のパーティションを探し、テーブルsbtest1の列「k」の最小値と最大値を確認します。

    mysql> USE sbtest3;
    mysql> SELECT min(k), max(k) FROM sbtest1;
    +--------+--------+
    | min(k) | max(k) |
    +--------+--------+
    | 232185 | 499998 |
    +--------+--------+
    よさそうだ。列「k」の最大値は、499,999の制限を超えません。このパーティションに格納される行数を確認しましょう:

    mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
           FROM INFORMATION_SCHEMA.PARTITIONS 
           WHERE TABLE_SCHEMA='sbtest3' 
           AND TABLE_NAME='sbtest1';
    +--------------+------------+----------------+------------+
    | TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
    +--------------+------------+----------------+------------+
    | sbtest3      | sbtest1    | p1             |       1815 |
    +--------------+------------+----------------+------------+

    それでは、他のMySQLサーバー(mysql2)を確認しましょう:

    mysql> USE sbtest3;
    mysql> SELECT min(k), max(k) FROM sbtest1;
    +--------+--------+
    | min(k) | max(k) |
    +--------+--------+
    | 500003 | 794952 |
    +--------+--------+
    このパーティションに格納される行数を確認しましょう:

    mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
           FROM INFORMATION_SCHEMA.PARTITIONS 
           WHERE TABLE_SCHEMA='sbtest3' 
           AND TABLE_NAME='sbtest1';
    +--------------+------------+----------------+------------+
    | TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
    +--------------+------------+----------------+------------+
    | sbtest3      | sbtest1    | p2             |       3247 |
    +--------------+------------+----------------+------------+

    見事! Sysbenchを使用して適切なデータ分割を行うシャーディングされたMySQLテストセットアップがあります。ハッピーベンチマーク!


    1. SQLServerで行を列に効率的に変換する

    2. ADO.NETがT-SQLストアドプロシージャを呼び出すと、SqlTimeoutExceptionが発生します

    3. SQLServerの文字列へのvarbinary

    4. RACVMをバックアップする方法