本記事では、並列インポートとデータ圧縮に関する使用方法について説明します。
一般的なユースケースは以下のとおりです:
データ移行:大量のデータをあるシステムから別のシステムに移行する必要がある場合、並列インポートを使用することでデータ移行の速度を大幅に向上させることができます。また、データ圧縮により、必要な転送帯域幅とストレージリソースの削減が可能です。
バックアップとリストア:データバックアップ時にデータ圧縮を使用することで、バックアップファイルのサイズを縮小し、ストレージ容量を節約できます。データリストア時に並列インポートを使用することで、データのリストア速度を向上させることができます。
カラムストアテーブル:カラムストアテーブルでクエリを実行する際、通常はクエリに関連する列にのみアクセスする必要があり、行全体のデータにアクセスする必要はありません。そのため、圧縮された列はそのままスキャンや処理が可能で、これによりI/O操作が削減され、クエリ速度と全体的なパフォーマンスが向上します。カラムストアテーブルの場合、データを一括インポートした後、データ圧縮を行うと、読み取りパフォーマンスが向上します。ただし、カラムストアテーブルのコンパクト速度は遅くなる可能性があるため注意が必要です。
並列インポート
Operational OLAPには、分析クエリ以外に、もう一つ非常に重要な要素があります。それは、大量データを並列でインポートする能力、すなわちデータの一括処理能力です。OceanBaseデータベースのパラレル実行フレームワークは、DML文のパラレル実行(Parallel DML、PDML)にも対応しています。複数ノードで構成されるデータベースでは、複数マシンによる並列書き込みを実現し、大規模トランザクションの一貫性を保証します。さらに、非同期ダンプメカニズムと組み合わせることで、メモリが逼迫した状況においても、LSM-Treeストレージエンジンによる大規模トランザクションの処理性能を大幅に向上させることができます。
次の例を通してPDMLを検証します:引き続き、TPC-Hのlineitemテーブルを基に、同じテーブル構造を持つ空テーブルlineitem2を作成します。その後、INSERT INTO ... SELECT文を用いて、1つのSQL文でlineitemテーブルの全600万行のデータを新しいlineitem2テーブルに挿入します。次に、PDMLを無効にした場合と有効にした場合でそれぞれ実行し、その効果と違いを観察します。
まず、lineitemのテーブル構造をコピーしてlineitem2を作成します。注意:OceanBaseデータベースでは、パーティションテーブルを使用してデータ拡張を行います。この例では16個のパーティションを使用しているため、対応するlineitem2も完全に同一である必要があります。
obclient [test]> SHOW CREATE TABLE lineitem\G
*************************** 1. row ***************************
Table: lineitem
Create Table: CREATE TABLE `lineitem` (
`l_orderkey` bigint(20) NOT NULL,
`l_partkey` bigint(20) NOT NULL,
`l_suppkey` bigint(20) NOT NULL,
`l_linenumber` bigint(20) NOT NULL,
`l_quantity` bigint(20) NOT NULL,
`l_extendedprice` bigint(20) NOT NULL,
`l_discount` bigint(20) NOT NULL,
`l_tax` bigint(20) NOT NULL,
`l_returnflag` char(1) DEFAULT NULL,
`l_linestatus` char(1) DEFAULT NULL,
`l_shipdate` date NOT NULL,
`l_commitdate` date DEFAULT NULL,
`l_receiptdate` date DEFAULT NULL,
`l_shipinstruct` char(25) DEFAULT NULL,
`l_shipmode` char(10) DEFAULT NULL,
`l_comment` varchar(44) DEFAULT NULL,
PRIMARY KEY (`l_orderkey`, `l_linenumber`),
KEY `I_L_ORDERKEY` (`l_orderkey`) BLOCK_SIZE 16384 LOCAL,
KEY `I_L_SHIPDATE` (`l_shipdate`) BLOCK_SIZE 16384 LOCAL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPACT COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 TABLEGROUP = 'x_tpch_tg_lineitem_order_group'
partition by key(l_orderkey)
(partition p0,
partition p1,
partition p2,
partition p3,
partition p4,
partition p5,
partition p6,
partition p7,
partition p8,
partition p9,
partition p10,
partition p11,
partition p12,
partition p13,
partition p14,
partition p15)
1 row in set
デフォルトモードで実行し、PDMLを有効化しない
lineitem2を作成後、デフォルト設定でパラレル処理を有効にせずに挿入します。これは600万行の大規模トランザクションであるため、OceanBaseデータベースのデフォルトのトランザクションタイムアウト値をより大きな値(単位:μs)に調整する必要があります。
# SET ob_query_timeout = 1000000000;
# SET ob_trx_timeout = 1000000000;
データを挿入します。実行結果は次のとおりです:
obclient [test]> INSERT INTO lineitem2 SELECT * FROM lineitem;
Query OK, 6001215 rows affected (1 min 47.312 sec)
Records: 6001215 Duplicates: 0 Warnings: 0
パラレル処理を有効にしない場合、単一トランザクションでの600万行のデータ挿入に、OceanBaseは107秒を要しました。
PDML実行の有効化
PDMLの実行オプションを有効にするため、Hintを追加します。再度挿入する前に、前回挿入したデータをクリアします。
obclient [test]> TRUNCATE TABLE lineitem2;
obclient [test]> INSERT /*+ parallel(16) enable_parallel_dml */ INTO lineitem2 SELECT * FROM lineitem;
今回の実行時間を見てみましょう:
obclient> TRUNCATE TABLE lineitem2;
Query OK, 0 rows affected (0.108 sec)
obclient> INSERT /*+ parallel(16) enable_parallel_dml */ INTO lineitem2 SELECT * FROM lineitem;
Query OK, 6001215 rows affected (22.117 sec)
Records: 6001215 Duplicates: 0 Warnings: 0
PDMLを有効化することで、同一テーブルへ600万行のデータを挿入するのにかかる時間は約22秒に短縮され、約5倍のパフォーマンス向上が確認できます。この機能は、ユーザーが一括データ処理を必要とするシナリオで特に有効です。
データ圧縮
OceanBase データベースは LSM-Tree 構造に基づき、独自のストレージエンジンを開発しました。データは、主にベースラインデータ(SSTable)と増分データ(MemTable)の2つに分類されます。ベースラインデータはディスクに保存され、増分変更はメモリ上で行われます。これにより、データをディスク上でよりコンパクトな方法で保存することができます。さらに、ディスク上のベースデータは頻繁に更新されない特性を活かし、OceanBaseは汎用圧縮アルゴリズムを用いてデータを再圧縮します。これにより、非常に高いデータ圧縮率を実現しています。しかも、このデータ圧縮はクエリや書き込みのパフォーマンスを損なうことはありません。ここでは、OceanBaseデータベースに大量の外部データをインポートし、データ圧縮率を確認する方法を解説します。
データの準備
まず、データ準備ツールCreateData.jarを使用して、5000万行のテストデータを/home/softディレクトリに生成します。データ生成には10~20分ほどかかります。なお、他のツールを使用して、ご自身でテストデータを準備することも可能です。
#mkdir /home/soft/
#java -jar CreateData.jar /home/soft/ 50000000
filePath is : /home/soft/
Start Time : 2022-07-10 15:33:00
End Time : 2022-07-10 15:52:53
#du -sh *
10G t_bigdata_loader.unl
OceanBaseデータベースは、CSV形式のデータをインポートする複数の方法をサポートしています。本記事では、Load Dataコマンドを使用した実行方法について説明します。
まず、生成されたファイルに名前を付け、実際のサイズを確認します。
# mv t_bigdata_loader.unl t_f1.csv # du -sh t_f1.csv 10G t_f1.csvt_f1.csvファイルの内容を確認すると、事前に生成されたCSVファイルには、ランダムアルゴリズムで取得した8列のデータが含まれており、それぞれ異なるデータ型に対応しています。したがって、OceanBaseのデータ圧縮機能を試すには、まずテナント内に対応するテーブルを作成し、このCSVファイルのデータをインポートする必要があります。1|1896404182|1980-06-01|2004-10-25 13:30:39|7470.689|33062564.9527|nOLqnBYtnp|BzWYjZjeodtBNzXSMyBduMNzwDPSiVmhVgPJMeEkeAwKBCorzblwovIHDKBsQhbVjQnIdoeTsiLXTNwyuAcuneuNaol| 2|572083440|2018-11-09|1998-07-11 01:23:28|6891.054|66028434.4013|UzqteeMaHP|vQWbWBXEWgUqUTzqsOSciiOuvWVcZSrlEOQDwDVGmvGRQYWmhCFdEkpsUsqrWEpKtmxSwURHIHxvmlXHUIxmfelYboeGEuScKKqzpuNLryFsStaFTTRqSsVlCngFFjHnEnpaCnWsdwztbiHJyoGkaxrFmyPAmVregfydArrUZsgRqBpQ| 3|1139841892|2006-10-07|1999-06-26 17:02:22|286.43692|51306547.5055|KJJtylgxkv|BuBdFTBIIFsEPVxsVBRqAnFXSBdtZDgfumUhIx| 4|1777342512|1982-12-18|2017-11-19 07:56:35|2986.242|85860387.8696|rTkUBWhdPt|JSazOTAmvtCBrINttDwublNJNRFDIiWkHtWZXmWgKHoZCKGqmmETkIcYLXiSgKkoaATNgjvPxVGjeCOODLEWqrQHqowbMjOLOKrtirWEOpUSxiUudZduTCUvZElKzZfggvCBNthwzKJc| ....testテナントのtestデータベースに、t_f1という名前のテーブルを作成します。テナントの作成手順については、テナント管理に関する記事を参照してください。# obclient -hxxx.xxx.xxx.xxx -P2881 -uroot@test -Dtest -A -p -c obclient [test]> CREATE TABLE t_f1(id DECIMAL(10,0),id2 DECIMAL(10,0),id3 DATE,id4 DATE,id5 FLOAT,id6 FLOAT,id7 VARCHAR(30),id8 VARCHAR(300));
データのインポート
OceanBaseデータベースに組み込まれているLoad Dataコマンドを使用してデータをインポートできます。Load Dataは並列インポートもサポートしています。インポート開始前に以下の設定を実行してください。Load Dataコマンドは、データファイルがOBServerノードのローカルパスに存在する場合にのみ使用できます。リモートからデータインポートする場合は、OceanBaseデータベースのobloaderツールをご利用ください。
obclient [test]> SET GLOBAL secure_file_priv = "/";
obclient [test]> GRANT FILE ON *.* to username;
注意
セキュリティ上の理由により、、secure_file_privを変更するSQL文は、ローカル接続のクライアントからのみ実行できます。詳細については、secure_file_priv を参照してください
設定完了後、セッションを再接続することで設定が有効になります。セッションのトランザクションタイムアウト時間を再設定し、実行中にタイムアウトで終了しないようにします。
obclient [test]> SET ob_query_timeout=1000000000;
obclient [test]> SET ob_trx_timeout=1000000000;
その後、インポート文を実行します:
obclient [test]> LOAD DATA /*+ parallel(16) */ INFILE '/home/soft/t_f1.csv' INTO table t_f1 fields TERMINATED BY '\|' LINES TERMINATED BY '\n';
並列インポートを有効にすると、10GBのデータの処理に約4分かかります。本記事ではテナントのCPU並列度を16に設定していますが、実際の構成に合わせて最適な並列度を設定できます。並列度が高いほど、インポート速度が向上します。
インポート後、データベースにアクセスし、このテーブルのレコード数とディスク容量を確認します。
テーブルのレコード数が5000万件であることを確認します。
obclient [test]> SELECT COUNT(*) FROM t_f1; +----------+ | count(*) | +----------+ | 50000000 | +----------+データをコンパクトします。
ベースラインデータの圧縮効果を確認するために、
rootユーザーでクラスタのsysテナントにログインし、データのコンパクトを手動でトリガーします。これにより、増分データとベースラインデータをコンパクトおよび圧縮できます。以下の方法で手動でコンパクトを実行できます。# obclient -h127.0.0.1 -P2881 -uroot@sys -Doceanbase -A -p -c obclient[oceanbase]> ALTER SYSTEM MAJOR FREEZE;次のクエリでIDLEが返される場合は、コンパクトが完了したことを示します。
obclient [oceanbase]> SELECT * FROM oceanbase.CDB_OB_MAJOR_COMPACTION; +-----------+---------------------+----------------------------+----------------------+---------------------+----------------------------+----------------------------+--------+----------+--------------+------+ | TENANT_ID | FROZEN_SCN | FROZEN_TIME | GLOBAL_BROADCAST_SCN | LAST_SCN | LAST_FINISH_TIME | START_TIME | STATUS | IS_ERROR | IS_SUSPENDED | INFO | +-----------+---------------------+----------------------------+----------------------+---------------------+----------------------------+----------------------------+--------+----------+--------------+------+ | 1 | 1679248800404017149 | 2023-03-20 02:00:00.404017 | 1679248800404017149 | 1679248800404017149 | 2023-03-20 02:00:44.035785 | 2023-03-20 02:00:00.442481 | IDLE | NO | NO | | | 1001 | 1679248804191204504 | 2023-03-20 02:00:04.191205 | 1679248804191204504 | 1679248804191204504 | 2023-03-20 02:00:46.094551 | 2023-03-20 02:00:04.218608 | IDLE | NO | NO | | | 1002 | 1679248802450394471 | 2023-03-20 02:00:02.450394 | 1679248802450394471 | 1679248802450394471 | 2023-03-20 02:00:33.818514 | 2023-03-20 02:00:02.484814 | IDLE | NO | NO | | 1 row in setsysテナントで以下のステートメントを実行することで、OceanBaseにインポートされたデータのストレージ使用状況を確認できます。
obclient [oceanbase]> select b.table_name,a.svr_ip,data_size/1024/1024/1024 from CDB_OB_TABLET_REPLICAS a,CDB_OB_TABLE_LOCATIONS b where a.tablet_id=b.tablet_id and b.table_name='T_F1'; +------------+---------------+----------------------------+ | table_name | svr_ip | a.data_size/1024/1024/1024 | +------------+---------------+----------------------------+ | t_f1 | xxx.xx.xxx.xx | 6.144531250000 | +------------+---------------+----------------------------+
圧縮後のテーブルサイズは約6.145GBで、圧縮率は10/6.145 = 1.62です。