INSERT
INSERT語句用于插入新的行數(shù)據(jù)至表中。本文為您介紹在實(shí)時(shí)數(shù)倉Hologres中如何使用INSERT插入數(shù)據(jù)。
命令介紹
您可以插入一個(gè)或多個(gè)由表達(dá)式指定的行,以及插入來自一個(gè)查詢的零行或多行數(shù)據(jù)至Hologres。語句如下。
INSERT INTO <schema>.<table> [( <column> [, ...] )]
VALUES ( {<expression>} [, ...] )
[, ...] | <query>}
參數(shù)說明如下。
參數(shù) | 描述 |
schema | 表所在的Schema名稱。 |
table | 已創(chuàng)建的表名稱。 通過Flink寫入時(shí)可以插入父表并自動(dòng)路由到子表。從Hologres V1.3版本起,支持符合FixedPlan的Insert語句直接寫入分區(qū)表父表,詳情請(qǐng)參見Fixed Plan加速SQL執(zhí)行。 |
column | table表中的某個(gè)列的名稱。 您也可以使用子域名或者數(shù)組下標(biāo)限定列名稱。(指向一個(gè)組合列的某些列中插入會(huì)讓其他域?yàn)榭眨?/p> |
expression | 賦予相應(yīng)列的表達(dá)式或值。 |
query | 需要被插入行的SELECT查詢語句。 語法詳情請(qǐng)參見SELECT語句。 |
目前INSERT只支持以下兩種數(shù)據(jù)寫入方式:
insert into values
:INSERT INTO holo2mysqltest (cate_id, cate_name) VALUES (3, 'true'), (3, 'fale'), (3, 'trxxue'), (3, 'x'), (4, 'The Dinner Game');
insert into select:
INSERT INTO test2 SELECT * FROM test1;
技術(shù)原理
Hologres表的存儲(chǔ)結(jié)構(gòu)分為行存、列存和行列共存,但三者的寫入原理一致。
如下圖所示,INSERT是以Append Only的方式寫入WAL,并實(shí)時(shí)更新到內(nèi)存表(MemTable),保證數(shù)據(jù)實(shí)時(shí)可見。但Mem Table有一定的大小,寫滿了之后會(huì)切換新的MemTable,并觸發(fā)后臺(tái)的異步Flush過程,將其中的數(shù)據(jù)逐漸Flush到文件中,文件存儲(chǔ)在Pangu中。在Flush的過程中會(huì)產(chǎn)生很多小文件,后臺(tái)會(huì)將這些小文件做合并和整理,即Compaction。為了寫速度盡可能的快,后臺(tái)會(huì)先將數(shù)據(jù)寫完,待異步Compaction時(shí)再執(zhí)行壓縮和整理,因此會(huì)看到在數(shù)據(jù)寫入過程中,數(shù)據(jù)的存儲(chǔ)會(huì)一定的膨脹,等數(shù)據(jù)寫入之后,Compaction完成后存儲(chǔ)會(huì)下降。
對(duì)于行存、列存、行列共存表的區(qū)別一方面是內(nèi)存的Mem Table的索引格式不同,另外一方面在Flush到文件的過程中:
行存表:會(huì)Flush成行存儲(chǔ)的文件,即SST格式。
列存表:會(huì)Flush成列存文件,即ORC格式。
行列共存表:會(huì)分別Flush為行存和列存兩種文件,SST和ORC格式,在Flush過程中會(huì)保證數(shù)據(jù)的一致性,只有行存、列存都同時(shí)Flush完成才會(huì)返回成功,同時(shí)在存儲(chǔ)上行列共存相當(dāng)于是兩份存儲(chǔ),因此行列共存的表在存儲(chǔ)上會(huì)有一定的犧牲。
使用限制
若是分區(qū)表,必須插入具體的子表,不能插入分區(qū)父表,且插入時(shí),對(duì)應(yīng)的分區(qū)字段值要和子表分區(qū)字段值一致。
目標(biāo)列的名稱可以以任意順序列出。如果使用
insert into select
的方式插入數(shù)據(jù),目標(biāo)列和查詢列類型需要一一對(duì)齊。
使用示例
Hologres從V2.1.17版本起支持Serverless Computing能力,針對(duì)大數(shù)據(jù)量離線導(dǎo)入、大型ETL作業(yè)、外表大數(shù)據(jù)量查詢等場景,使用Serverless Computing執(zhí)行該類任務(wù)可以直接使用額外的Serverless資源,避免使用實(shí)例自身資源,無需為實(shí)例預(yù)留額外的計(jì)算資源,顯著提升實(shí)例穩(wěn)定性、減少OOM概率,且僅需為任務(wù)單獨(dú)付費(fèi)。Serverless Computing詳情請(qǐng)參見Serverless Computing概述,Serverless Computing使用方法請(qǐng)參見Serverless Computing使用指南。
插入普通表。
CREATE TABLE holotest ( a int, b bigint, c bool, e decimal(38,10), f text, g timestamp, h timestamptz, i jsonb, j int[] ); -- (可選)推薦使用Serverless Computing執(zhí)行大數(shù)據(jù)量離線導(dǎo)入和ETL作業(yè) SET hg_computing_resource = 'serverless'; -- 導(dǎo)入數(shù)據(jù) INSERT INTO holotest VALUES (1,9223372036854775807,false,123.123456789123,'john','2020-01-01 01:01:01.123456', '2004-10-19 10:23:54+08','{"a":2}',ARRAY[1, 2, 3, 4]); -- 重置配置,保證非必要的SQL不會(huì)使用serverless資源。 RESET hg_computing_resource;
從a表插入數(shù)據(jù)至b表。
CREATE TABLE holotest2( a int, b bigint, c bool); -- (可選)推薦使用Serverless Computing執(zhí)行大數(shù)據(jù)量離線導(dǎo)入和ETL作業(yè) SET hg_computing_resource = 'serverless'; -- 導(dǎo)入數(shù)據(jù) INSERT INTO holotest2 (a,b,c) SELECT a,b,c FROM holotest; -- 重置配置,保證非必要的SQL不會(huì)使用serverless資源。 RESET hg_computing_resource;
插入分區(qū)表數(shù)據(jù)。
--示例:在public schema下創(chuàng)建不帶主鍵的分區(qū)父表和對(duì)應(yīng)的分區(qū)子表 BEGIN; CREATE TABLE public.hologres_parent( a text, b int, c timestamp, d text ) PARTITION BY list(a); CALL set_table_property('public.hologres_parent', 'orientation', 'column'); CREATE TABLE public.hologres_2022 partition of public.hologres_parent for values in('2022'); CREATE TABLE public.hologres_2021 partition of public.hologres_parent for values in('2021'); CREATE TABLE public.hologres_2020 partition of public.hologres_parent for values in('2020'); COMMIT; -- (可選)推薦使用Serverless Computing執(zhí)行大數(shù)據(jù)量離線導(dǎo)入和ETL作業(yè) SET hg_computing_resource = 'serverless'; --插入分區(qū)子表 INSERT INTO public.hologres_2022 values('2022',1,now(),'a') -- 重置配置,保證非必要的SQL不會(huì)使用serverless資源。 RESET hg_computing_resource;
常見問題
問題一:大數(shù)據(jù)量寫入時(shí),實(shí)例CPU和內(nèi)存資源使用率100%,影響實(shí)例其他寫入與查詢?nèi)蝿?wù)。
建議使用Serverless Computing能力執(zhí)行大數(shù)據(jù)量寫入任務(wù)。
說明Hologres從V2.1.17版本起支持Serverless Computing能力,針對(duì)大數(shù)據(jù)量離線導(dǎo)入、大型ETL作業(yè)、外表大數(shù)據(jù)量查詢等場景,使用Serverless Computing執(zhí)行該類任務(wù)可以直接使用額外的Serverless資源,避免使用實(shí)例自身資源,無需為實(shí)例預(yù)留額外的計(jì)算資源,顯著提升實(shí)例穩(wěn)定性、減少OOM概率,且僅需為任務(wù)單獨(dú)付費(fèi)。Serverless Computing詳情請(qǐng)參見Serverless Computing概述,Serverless Computing使用方法請(qǐng)參見Serverless Computing使用指南。
問題二:數(shù)據(jù)在寫入時(shí),為什么監(jiān)控指標(biāo)中存儲(chǔ)用量上漲非常多,寫入完成后存儲(chǔ)用量又下降?
根據(jù)寫入的技術(shù)原理,為了盡可能快地寫入數(shù)據(jù),后臺(tái)會(huì)先將數(shù)據(jù)寫完,待異步Compaction時(shí)再執(zhí)行壓縮和整理,因此會(huì)看到在數(shù)據(jù)寫入過程中,數(shù)據(jù)的存儲(chǔ)會(huì)一定的膨脹,等數(shù)據(jù)寫入之后,Compaction完成后存儲(chǔ)會(huì)下降。
問題三:同一張表并行執(zhí)行
insert
命令時(shí),延遲增加。沒有走Fixed Plan的
insert
是表鎖,并行執(zhí)行insert
會(huì)導(dǎo)致等鎖時(shí)間增加,從而造成延遲增加。問題四:數(shù)據(jù)寫入分區(qū)父表報(bào)錯(cuò):
ERROR: no partition of relation "<table_name>" found for row
。報(bào)錯(cuò)信息:
ERROR: no partition of relation "<table_name>" found for row
。問題原因:分區(qū)子表不存在。
解決方法:寫入數(shù)據(jù)前,需創(chuàng)建對(duì)應(yīng)的分區(qū)子表,命令示例如下。
CREATE TABLE <child_table_name> partition of <parent_table_name> for values in (<value>);
問題五:在導(dǎo)入數(shù)據(jù)的時(shí)候報(bào)錯(cuò):
Currently inserting into parent table is not supported
。報(bào)錯(cuò)信息:導(dǎo)入數(shù)據(jù)時(shí)報(bào)錯(cuò):
Currently inserting into parent table is not supported
。問題原因:當(dāng)前Insert的表,是一張分區(qū)父表,Hologres不支持直接寫入分區(qū)父表。
解決方法:需要寫入對(duì)應(yīng)的分區(qū)子表。