すべてのプロダクト
Search
ドキュメントセンター

E-MapReduce:挿入

最終更新日:Apr 09, 2025

Insert Intoインポート方式は、INSERT INTOステートメントに基づいています。 MySQLなどのデータベースと同様の方法で、DorisでINSERT INTOステートメントを実行できます。ただし、データは独立したインポートジョブを使用してDorisに挿入されます。したがって、INSERT INTOもDorisのインポート方式と見なされます。このトピックでは、INSERT INTOステートメントを使用してデータをインポートする方法とベストプラクティスについて説明します。

背景情報

説明

このトピックの一部の情報はApache Dorisからのものです。 詳細については、「Apache Dorisの概要」をご参照ください。

Dorisは、INSERT INTOステートメントの次の構文をサポートしています。

  • INSERT INTO tbl SELECT ...

  • INSERT INTO tbl (col1, col2, ...) VALUES (1, 2, ...), (1,3, ...);

    重要

    この構文はデモでのみ使用できます。テスト環境または本番環境では使用しないでください。

インポート操作と返される結果

MySQLプロトコルを使用してINSERT INTOステートメントを送信する必要があります。 INSERT INTOステートメントを実行すると、結果は同期的に返されます。

インポート操作

INSERT INTOステートメントの例:

INSERT INTO tbl2 WITH LABEL label1 SELECT * FROM tbl3;
INSERT INTO tbl1 VALUES ("qweasdzxcqweasdzxc"), ("a");
重要

共通テーブル式(CTE)を使用してINSERT INTOステートメントでサブクエリを定義する場合は、WITH LABELと列リストを指定するか、CTEをラップする必要があります。次のステートメント例をご参照ください。

INSERT INTO tbl1 WITH LABEL label1
WITH cte1 AS (SELECT * FROM tbl1), cte2 AS (SELECT * FROM tbl2)
SELECT k1 FROM cte1 JOIN cte2 WHERE cte1.k1 = 1;

INSERT INTO tbl1 (k1)
WITH cte1 AS (SELECT * FROM tbl1), cte2 AS (SELECT * FROM tbl2)
SELECT k1 FROM cte1 JOIN cte2 WHERE cte1.k1 = 1;

INSERT INTO tbl1 (k1)
select * from (
WITH cte1 AS (SELECT * FROM tbl1), cte2 AS (SELECT * FROM tbl2)
SELECT k1 FROM cte1 JOIN cte2 WHERE cte1.k1 = 1) as ret

上記のステートメント例の パラメーターの詳細については、「INSERT INTO」をご参照ください。 HELP INSERT コマンドを実行して、パラメーターの説明を表示することもできます。

返される結果

INSERT INTOステートメントはSQLステートメントです。返される結果は、次の場合によって異なります。

  • 結果セットが空です。

    INSERT INTOステートメントのSELECT句の結果セットが空の場合、次のような出力が返されます。

    mysql> insert into tbl1 select * from empty_tbl;
    Query OK, 0 rows affected (0.02 sec)

    Query OK は、ステートメントが正常に実行されたことを示します。 0 rows affected は、データがインポートされていないことを示します。

  • 結果セットが空ではありません。

    結果セットが空でない場合、返される結果は、INSERTステートメントが正常に実行されたかどうかによって異なります。

    • INSERT INTOステートメントが正常に実行されました。

      mysql> insert into tbl1 select * from tbl2;
      Query OK, 4 rows affected (0.38 sec)
      {'label':'insert_8510c568-9eda-4173-9e36-6adc7d35****', 'status':'visible', 'txnId':'4005'}
      
      mysql> insert into tbl1 with label my_label1 select * from tbl2;
      Query OK, 4 rows affected (0.38 sec)
      {'label':'my_label1', 'status':'visible', 'txnId':'4005'}
      
      mysql> insert into tbl1 select * from tbl2;
      Query OK, 2 rows affected, 2 warnings (0.31 sec)
      {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4****', 'status':'visible', 'txnId':'4005'}
      
      mysql> insert into tbl1 select * from tbl2;
      Query OK, 2 rows affected, 2 warnings (0.31 sec)
      {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4****', 'status':'committed', 'txnId':'4005'}

      Query OK は、ステートメントが正常に実行されたことを示します。 4 rows affected は、4行のデータがインポートされたことを示します。 2 warnings は、2 行のデータが除外されたことを示します。

      JSON文字列も返されます。例:

      {'label':'my_label1', 'status':'visible', 'txnId':'4005'}
      {'label':'insert_f0747f0e-7a35-46e2-affa-13a235f4****', 'status':'committed', 'txnId':'4005'}
      {'label':'my_label1', 'status':'visible', 'txnId':'4005', 'err':'some other error'}
      • label:指定したラベル、またはシステムによって自動的に生成されたラベル。ラベルは、INSERT INTOジョブを識別するために使用されます。各インポートジョブは、単一のデータベース内で一意のラベルを持ちます。

      • status:インポートされたデータが表示されるかどうかを示します。 visible が返された場合、インポートされたデータが表示されます。 committed が返された場合、インポートされたデータは表示されません。

      • txnId:INSERT INTOステートメントのトランザクションのID。

      • err:予期しないエラー。

      SHOW LOADステートメントを実行して、除外されたデータ行を表示できます。次のステートメント例をご参照ください。返された結果のURLを使用して、エラーデータをクエリできます。

      show load where label="xxx";

      committed 状態は一時的な状態です。データは最終的に visible 状態になります。 SHOW TRANSACTIONステートメントを実行して、インポートされたデータが表示されるかどうかを確認できます。次のステートメント例をご参照ください。返された結果の TransactionStatus パラメーターの値が visible の場合、データが表示されます。

      show transaction where id=4005;
    • INSERT INTOステートメントの実行に失敗しました。

      INSERT INTOステートメントの実行に失敗した場合、データはインポートされません。返される結果の例:

      mysql> insert into tbl1 select * from tbl2 where k1 = "a";
      ERROR 1064 (HY000): all partitions have no load data. url: http://10.74.xx.xx:8042/api/_load_error_log?file=__shard_2/error_log_insert_stmt_ba8bb9e158e4879-ae8de8507c0b****_ba8bb9e158e4879_ae8de8507c0b****

      返された結果の ERROR 1064 (HY000): all partitions have no load data メッセージは、失敗の原因を示しています。 URL を使用して、エラーデータをクエリできます。

要約すると、INSERT INTOステートメントの返された結果を解釈し、次のロジックに基づいて後続の操作を実行できます。

  • ERROR 1064 (HY000) が返された場合、インポートは失敗します。

  • Query OK が返された場合、ステートメントは正常に実行されます。

    • 影響を受けた行数が 0 の場合、結果セットは空で、データはインポートされません。

    • 影響を受けた行数が 0 より大きい場合、返された結果の他のパラメーターをさらに確認します。

      • status パラメーターの値が committed の場合、データは表示されません。この場合、SHOW TRANSACTIONステートメントを実行して、データが表示されるまでデータの状態を確認できます。

      • status パラメーターの値が visible の場合、インポートは成功です。

      • 警告の数が 0 より大きい場合、1 つ以上のデータ行が除外されています。この場合、SHOW LOADステートメントを実行して、除外されたデータ行を表示するためのURLを取得できます。

SHOW LAST INSERT

前のセクションでは、INSERT INTOステートメントの返された結果に基づいて後続の操作を実行する方法について説明しました。ただし、特定の言語のMySQLクラスライブラリを使用して、返された結果のJSON文字列を取得することは困難です。したがって、Dorisでは、SHOW LAST INSERTコマンドを実行して、最新のINSERT INTOステートメントの返された結果を明示的に取得できます。 INSERT INTOステートメントを実行した後、同じセッションで SHOW LAST INSERT コマンドを実行して、最新のINSERT INTOステートメントの返された結果を取得できます。例:

mysql> show last insert\G
*************************** 1. row ***************************
    TransactionId: 640**
            Label: insert_ba8f33aea9544866-8ed77e2844d0****
         Database: default_cluster:db1
            Table: t1
TransactionStatus: VISIBLE
       LoadedRows: 2
     FilteredRows: 0

このコマンドは、最新のINSERT INTOステートメントの結果とトランザクションの詳細を返します。 INSERT INTOステートメントを実行するたびに SHOW LAST INSERT コマンドを実行して、INSERT INTOステートメントの返された結果を取得できます。

重要

同じセッションの接続中にこのコマンドを実行して、最新のINSERT INTOステートメントの返された結果のみを取得できます。接続が閉じられたり、置き換えられたりすると、空の結果セットが返されます。

関連するシステムパラメーター

FE構成

timeout:インポートジョブのタイムアウト期間。単位:秒。指定されたタイムアウト期間内にインポートジョブが完了しない場合、システムはジョブをキャンセルします。この場合、ジョブは CANCELLED 状態になります。 INSERT INTOジョブに対して個別にカスタムタイムアウト期間を指定することはできません。すべてのINSERT INTOジョブに同じタイムアウト期間が適用されます。デフォルトのタイムアウト期間は 1 時間です。デフォルトのタイムアウト期間内にデータをインポートできない場合は、フロントエンド(FE)の insert_load_default_timeout_second パラメーターを変更できます。また、INSERT INTOステートメントは、query_timeoutセッション変数で指定されたタイムアウト期間の影響も受けます。 SET query_timeout = xxx; コマンドを実行することで、タイムアウト期間を延長できます。タイムアウト期間は秒単位で測定されます。

セッション変数

  • enable_insert_strict:INSERT INTOステートメントでは、許容できる失敗率を指定することはできません。 enable_insert_strictセッション変数を設定して、INSERT INTOステートメントの許容できる失敗率を制御できます。 false を指定すると、少なくとも 1 つのデータ行がインポートされた場合に成功の結果が返されます。一部のデータ行のインポートに失敗した場合でも、ラベルも返されます。 true を指定すると、データ行のインポートに失敗した場合にインポートは失敗します。デフォルト値は false です。 SET enable_insert_strict = true; コマンドを実行して、変数を true に設定できます。

  • query_timeout:INSERT INTOステートメントはSQLステートメントです。したがって、INSERT INTOステートメントは、query_timeoutセッション変数で指定されたタイムアウト期間の影響を受けます。 SET query_timeout = xxx; コマンドを実行することで、タイムアウト期間を延長できます。タイムアウト期間は秒単位で測定されます。

ベストプラクティス

シナリオ

  • Dorisの機能をテストするために、少数のデータ行をインポートします。このシナリオでは、MySQLデータベースの場合と同じように、INSERT INTO VALUES構文を使用できます。

  • Dorisテーブルのデータに対して抽出、変換、ロード(ETL)処理を実行し、処理されたデータを別のDorisテーブルにインポートします。この場合、INSERT INTO SELECT構文の方が適しています。

  • 外部テーブルを作成し、テーブルをデータソースにマップします。たとえば、MySQLテーブルをマップするMySQL外部テーブルを作成するか、Hadoop Distributed File System(HDFS)のデータファイルをマップするbroker外部テーブルを作成します。次に、INSERT INTO SELECTステートメントを実行して、データソースのデータをDorisテーブルにインポートします。

データサイズ

Dorisは、INSERT INTOステートメントによってインポートできるデータのサイズを制限しません。 INSERT INTOステートメントを実行して、大量のデータをインポートできます。ただし、INSERT INTOジョブにはデフォルトのタイムアウト期間が指定されています。インポートするデータのサイズが大きく、デフォルトのタイムアウト期間内にデータをインポートできないと推定される場合は、インポートジョブのタイムアウト期間を延長する必要があります。

たとえば、インポートするデータのサイズが 36 GB の場合、次の式に基づいてデータのインポートに必要な時間を計算できます。 36 GB / 10 MB / s = 3600 秒。この式では、10 MB / sは最大インポート速度です。クラスターの状態に基づいて平均インポート速度を計算し、式で 10 MB / s を置き換える必要があります。

完全な例

salesデータベースには、store_salesという名前のテーブルがあります。 bj_store_salesという名前のテーブルが作成されます。 store_salesテーブルから bj_store_salesテーブルに bj 地域のデータをインポートします。インポートするデータのサイズは約 10 GB で、現在のクラスターの平均インポート速度は約 5 MB / s です。

store_sales スキーマ:
(id, total, user_id, sale_timestamp, region)

bj_store_sales スキーマ:
(id, total, user_id, sale_timestamp)
  1. INSERT INTOジョブのデフォルトのタイムアウト期間を変更するかどうかを決定します。

    データのインポートに必要な概算時間を計算する
    10 GB / 5 M/s = 2000 秒
    
    FE でタイムアウト期間を変更する
    insert_load_default_timeout_second = 2000
  2. インポートジョブを作成します。

    ソーステーブルのデータに対してETL処理を実行し、処理されたデータをデスティネーションテーブルにインポートします。サブクエリを含むINSERT INTOステートメントは、このシナリオに適しています。

    INSERT INTO bj_store_sales WITH LABEL `label` SELECT id, total, user_id, sale_timestamp FROM store_sales where region = "bj";