日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

Insert Into

Insert Into語句的使用方式和MySQL等數據庫中Insert Into語句的使用方式類似。在Doris中,所有的數據寫入都是一個獨立的導入作業。因此,文本將Insert Into作為一種導入方式,介紹Insert Into的使用方法和最佳實踐。

背景信息

說明

本文部分內容來源于Apache Doris,詳情請參見Doris介紹。

主要的Insert Into命令包含以下兩種:

  • NSERT INTO tbl SELECT ...

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

    重要

    該命令僅用于Demo,請勿使用在測試或生產環境中。

導入操作及返回結果

Insert Into命令需要通過MySQL協議提交,創建導入請求會同步返回導入結果。

導入操作

Insert Into的使用示例如下:

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

當需要使用CTE(Common Table Expressions) 作為insert操作中的查詢部分時,必須指定WITH LABEL和column list部分或者對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對應Select語句的結果集為空,返回示例如下。

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

    Query OK表示執行成功,0 rows affected表示沒有數據被導入。

  • 結果集不為空

    在結果集不為空的情況下,返回結果分為如下幾種情況:

    • Insert執行成功并可見。

      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表示被過濾的行數。

      同時會返回一個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:您指定的Label或自動生成的Label。Label是該Insert Into導入作業的標識,每個導入作業都有一個在單database內部唯一的Label。

      • status:表示導入數據是否可見。如果可見,顯示visible,如果不可見,顯示committed。

      • txnId:該Insert對應的導入事務的id。

      • err:顯示一些其他非預期錯誤。

      您可以使用SHOW LOAD語句查看被過濾的行,示例如下。返回結果中的URL可以用于查詢錯誤的數據。

      show load where label="xxx";

      數據不可見是一個臨時狀態,數據最終是一定可見的??梢酝ㄟ^SHOW TRANSACTION語句查看這批數據的可見狀態,示例如下。返回結果中的TransactionStatus列如果為visible,則表述數據可見。

      show transaction where id=4005;
    • Insert執行失敗。

      執行失敗表示沒有任何數據被成功導入,返回示例如下。

      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操作返回結果的正確處理邏輯為:

  • 如果返回結果為ERROR 1064 (HY000),則表示導入失敗。

  • 如果返回結果為Query OK,則表示執行成功。

    • 如果rows affected為0,表示結果集為空,沒有數據被導入。

    • 如果rows affected大于0:

      • 如果status為committed,表示數據不可見,需要通過SHOW TRANSACTION語句查看狀態直到visible。

      • 如果status為visible,表示數據導入成功。

      • 如果warnings大于0,表示有數據被過濾,可以通過SHOW LOAD語句獲取URL查看被過濾的行。

SHOW LAST INSERT

上面介紹了如何根據Insert操作的返回結果進行后續處理。但一些語言的MySQL類庫中很難獲取返回結果中的JSON字符串。因此,Doris還提供了SHOW LAST INSERT命令來顯式的獲取最近一次Insert操作的結果。當執行完一個Insert操作后,可以在同一Session連接中執行SHOW LAST INSERT,該命令會返回最近一次Insert操作的結果。例如:

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以及對應事務的詳細信息。因此,您可以在每次執行完Insert操作后,繼續執行show last insert命令來獲取Insert的結果。

重要

該命令只會返回在同一Session連接中,最近一次Insert操作的結果。如果連接斷開或更換了新的連接,則將返回空集。

相關系統配置

FE配置

timeout:導入任務的超時時間(以秒為單位)。導入任務在設定的timeout時間內未完成則會被系統取消,變成CANCELLED。目前Insert Into暫不支持自定義導入的timeout時間,所有Insert Into導入的超時時間是統一的,默認的timeout 時間為1小時。如果導入的源文件無法在規定時間內完成導入,則需要調整FE的參數insert_load_default_timeout_second。同時Insert Into語句受到Session變量query_timeout的限制,可以通過SET query_timeout = xxx; 來增加超時時間,單位是秒。

Session變量

  • enable_insert_strict:Insert Into導入本身不能控制導入可容忍的錯誤率。您只能通過Session參數enable_insert_strict控制。當該參數設置為false時,表示至少有一條數據被正確導入,則返回成功;如果有失敗數據,則還會返回一個Label。當該參數設置為true時,表示如果有一條數據錯誤,則導入失敗。默認為false??赏ㄟ^SET enable_insert_strict = true;來設置。

  • query_timeout:Insert Into本身也是一個SQL命令,因此也受到Session變量query_timeout的限制??梢酝ㄟ^SET query_timeout = xxx;來增加超時時間,單位是秒。

最佳實踐

應用場景

  • 僅導入幾條測試數據,驗證Doris系統的功能,適合使用INSERT INTO VALUES語法,其與MySql語法相同。

  • 將已經在Doris表中的數據進行ETL轉換并導入到一個新的Doris表中,適合使用INSERT INTO SELECT語法。

  • 創建一種外部表,如MySQL外部表映射一張MySQL系統中的表,或者創建Broker外部表來映射HDFS上的數據文件。然后通過INSERT INTO SELECT語法將外部表中的數據導入到Doris表中存儲。

數據量

Insert Into對數據量沒有限制,也支持大數據量導入。但Insert Into有默認的超時時間,如果您預估的導入數據量過大,需要修改系統的Insert Into導入超時時間。

例如,當導入數據量為36 GB時,導入時間約小于等于3600s*10 M/s。其中10 M/s是最大導入限速,您需要根據當前集群情況計算出平均的導入速度來替換公式中的10 M/s。

完整示例

在數據庫sales中有表store_sales,又新建表bj_store_sales,希望將store_sales中銷售記錄在bj的數據導入到表bj_store_sales中,導入的數據量約為10 GB,當前集群的平均導入速度約為5 M/s。

store_sales schema:
(id, total, user_id, sale_timestamp, region)

bj_store_sales schema:
(id, total, user_id, sale_timestamp)
  1. 判斷是否要修改Insert Into的默認超時時間。

    計算導入的大概時間
    10 GB / 5 M/s = 2000s
    
    修改FE配置
    insert_load_default_timeout_second = 2000
  2. 創建導入任務。

    由于希望將一張表中的數據做ETL并導入到目標表中,所以應該使用Insert into query_stmt方式導入。

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