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