本文為您介紹對錶執行DML操作過程中的常見問題。
問題類別 | 常見問題 |
插入或更新資料 | |
刪除資料 |
執行INSERT操作過程中出現錯誤,會損壞原有資料嗎?
不會損壞原有資料。MaxCompute滿足原子性,INSERT操作執行成功則更新資料,INSERT操作執行失敗則復原資料。
執行INSERT INTO或INSERT OVERWRITE操作時,提示Table xxx has n columns,but query has m columns
,如何解決?
執行INSERT INTO或INSERT OVERWRITE操作插入資料時,需要保證SELECT得到的欄位和目標表的欄位匹配,匹配內容包括順序、欄位類型和總的欄位數量。MaxCompute不支援插入表的指定欄位,其他欄位為NULL或者其他預設值時,您可以在SELECT時設定為NULL,例如select 'a', null, col_name from table_name;
。
執行INSERT INTO或INSERT OVERWRITE操作時,報錯a single instance cannot output data to more than 10000 partitions,如何解決?
問題現象
在INSERT INTO或INSERT OVERWRITE操作時,返回報錯如下。
FAILED: ODPS-0123031:Partition exception - a single instance cannot output data to more than 10000 partitions
產生原因
雖然單個MaxCompute表允許有6萬個分區,但是單個作業涉及的輸出表分區數量只允許有10000個。出現這個錯誤,通常是因為分區欄位設定有誤,例如根據ID欄位分區造成分區過多。
解決措施
一般作業輸出動態分區數達到幾千已經很大,超過10000可能存在商務邏輯或SQL文法問題。如無邏輯或文法問題,建議修改分區表的分區欄位,或將商務邏輯拆分為多個作業,避免出現該錯誤。
向MaxCompute表中插入動態分區時,報錯invalid dynamic partition value,如何解決?
問題現象
執行插入動態分區操作時,返回報錯如下。
FAILED: ODPS-0123031:Partition exception - invalid dynamic partition value: province=上海
產生原因
使用了非法的動態分區。動態分區是根據指定欄位進行分區,不支援特殊字元和中文動態分區欄位。
解決措施
插入動態分區時,需要注意如下情況:
在分布式環境下執行插入動態分區操作時,單個進程最多隻能輸出512個動態分區。
任意動態分區SQL不允許產生超過2000個動態分區。
動態產生的分區值不允許為NULL。
如果目標表有多級分區,在執行INSERT操作時,允許指定部分分區為靜態,但是靜態分區必須是進階分區。
向MaxCompute表中插入FLOAT類型的資料報錯,如何解決?
MaxCompute 2.0支援的基礎資料型別 (Elementary Data Type)請參見資料類型版本說明。其中:FLOAT資料類型沒有常量定義,若要插入該類型資料,可以使用CAST函數轉換資料類型。例如cast(5.1 as float)
將字串'5.1'
轉為FLOAT類型5.1
。
MaxCompute SQL中使用到新資料類型(TINYINT、SMALLINT、INT、FLOAT、VARCHAR、TIMESTAMP或BINARY)時,需要執行如下語句開啟新資料類型開關:
Session層級:如果使用新資料類型,您需要在SQL語句前加上
set odps.sql.type.system.odps2=true;
,並與SQL語句一起提交執行。Project層級:執行
setproject odps.sql.type.system.odps2=true;
開啟Project層級的新資料類型。該命令需要專案所有者執行。
對相同資料執行INSERT SELECT操作和SELECT操作的結果為什麼不一致?
問題現象
對相同的STRING類型欄位分別執行SQL語句,出現小數位不統一的現象。執行SELECT操作保留2位小數,執行INSERT SELECT操作,結果顯示多個小數位。
產生原因
對於INSERT SELECT操作,原始欄位類型是STRING,在隱式轉換為目標類型DECIMAL的過程中,先轉換為DOUBLE類型,然後在DOUBLE類型資料的基礎上執行ROUND操作。由於DOUBLE類型本身是不精確的,雖然執行了ROUND操作,但是依然可能顯示多個小數位。
解決措施
建議使用顯式轉換方式,增加如下語句通過CAST顯示轉換為DECIMAL類型。
case when pcm.abc is null then 0 else round(cast(pcm.abc as decimal) ,2) end abc
目標表的欄位類型為VARCHAR(10),插入資料溢出時會報錯嗎?
對VARCHAR(10)
資料類型的欄位插入資料時,資料長度溢出時會截斷並不報錯。
在執行MaxCompute SQL過程中,報錯Transaction timeout because cannot acquire exclusive lock,如何解決?
問題現象
執行MaxCompute SQL的過程中,返回報錯如下。
Failed to run ddltask - Modify DDL meta encounter exception : ODPS-0121096:MetaStore transaction conflict - Reached maximum retry times because of OTSStorageTxnLockKeyFail(Inner exception: Transaction timeout because cannot acquire exclusive lock.)
產生原因
MaxCompute允許多個作業同時寫入資料到單個表。當多個作業同時處於中繼資料提交階段時,每個作業都需要對單表表上的中繼資料加鎖、寫入、再解鎖。如果同時多個作業寫入,該表中繼資料總是處於加鎖寫入的狀態,可能出現部分作業在嘗試加鎖逾時之前一直沒有搶到鎖,從而導致報錯
cannot acquire exclusive lock
(作業嘗試加鎖逾時時間大約半分鐘,超過則報錯,加鎖粒度為表級)。簡而言之,同時寫表中繼資料的作業太多或者中繼資料寫入量太大(如大量分區寫入)時,並發寫入同一張表中繼資料的另一個作業可能會加鎖逾時導致報錯。解決措施
您需要檢查是否存在同時多次對錶或表分區執行讀寫操作的情況,建議不要同時對一張表或表分區執行多次讀寫操作。
如何更新MaxCompute表或分區中的資料?
MaxCompute支援通過update
操作,在行層級更新Transactional表中的資料。
如果表非Transactional表,您需要把來源資料分割或源表中的資料匯入到新分區或新表中,在匯入處理程序中執行相應的更新邏輯操作。新分區或新表可以與來源資料分割或源表相同,即就地更新。
如何刪除MaxCompute表或分區中的資料?
MaxCompute支援通過delete
操作,在行層級刪除Transactional表中的資料。
如果表非Transactional表,您可以通過如下方法刪除:
執行
drop
命令刪除表,達到刪除資料的目的。如果是非分區表,您可以執行
truncate table table_name;
命令清空表資料或通過insert overwrite
命令實作類別似的功能。樣本一:刪除TableA表中Col=1的資料,命令樣本如下。
insert overwrite table TableA select a,b,c.... from TableA where Col <> 1;
樣本二:刪除全部資料。
insert overwrite table TableA select a,b,c.... from TableA where 1=2;
如果是分區表,您可以執行
alter table table_name drop if exists partition(分區名='具體分區值')
命令,刪除對應的分區,即可刪除分區對應的資料。例如,表testtable的分區列為ds,執行如下命令刪除
ds='20170520'
的分區。alter table testtable drop if exists partition (ds='20170520');
使用INSERT和WHERE條件,將需要的資料匯入到另一個新分區或新表中。INSERT支援源表和目標表相同。
insert overwrite table sale_detail select * from sale_detail where name='mengyonghui';
如果表資料量較大,如何刪除非分區表中的重複資料?
如果每一列都一樣,您可以對所有列執行GROUP BY操作。例如,非分區表table1的列為c1,c2和c3,您可以執行如下命令。
insert overwrite table table1 select c1, c2, c3 from table1 group by
c1, c2, c3;
建議您在執行此操作前,做好資料備份工作並根據資料量評估此方式的代價是否比重新匯入的代價低。