hive實踐之map類型插入單條數據


  hive原本不是用來做簡單的crud的,但有時候我們就是有可能這么干,怎么辦呢?

  hive 還是提供了相應的功能的,查詢是最必須的,就無須多說了。

  插入數據一般來說都是大批量的插入,一般用於從源數據中導入數據到hive中,然后經過hive加工后,寫入到一張新的結果表。而這個表的數據一般也會很大,具體看業務復雜性。

  更新數據一般是不會被支持的,尤其是想更新某一條數據,但我們可以通過重新刷入數據的方式,達到更新數據的目的。一般hive表會有相應的分區要求,這樣就可以做一定程度上的數據索引效果,以及減少大數據的量。而其底層存儲為一個分區,一系列分組文件。

  刪除數據就更是沒有了,不過與更新數據一樣的道理,我們可以通過重新進行數據加工,刷入新數據集即可完成刪除的目的。不過,要想剔除其中一條數據,這個加工邏輯得好好想想了。

 

1. select查詢

  這個最復雜的,也是最核心的。基本遵循sql92協議,也就是說基本上你會寫sql, 就可以搞hive了。差別在於,hive會有很多自己支持的數據結構,以及很多特有的函數調用。另外,就是可以很方便地讓用戶自定義一些函數,以便滿足業務需求。即udf. 因此,如果你不清楚這些udf如何使用,那么你就缺失了這方面的技能了。

  舉一個例子說明即可:

with a as (
    select * from test_001 where pt='20210101'
),
 b as (
    select * from test_002 where pt='20200101'
 )
    select trim(a.name) name, 
        a.t_map['field1'] map_f1, 
        COALESCE(t1.f2, t2.f2) f2, 
        case when t1.money>1000 then 'G' else 'H' end
    from a join b on a.uid = b.uid

  總之一句話,你可以用sql表達非常復雜的業務邏輯。比如數據開發同學的重要利器就是這玩意。從一定角度上說,sql也是一門編程開發語言!驕傲了!

 

2. insert數據插入

  hive之類的大數據處理工具,一般只會支持大批量的插入。為什么呢?因為它的底層存儲就是一個個地大文件,方便實現啊,效率高啊啥的!所以,一般地,又會多出來一個概念,分區!因為是一個個地文件,在處理的時候,能做確定數據在哪個文件上,那么它效率就會很高了。

  而像關系型數據庫的索引之類的東西,這些大數據工具就不太方便有了,為什么呢?因為有大量的數據存儲着,如果想要專門去建立索引,那么這個存儲成本啊運算成本啊啥的,肯定就上去了。而最后可能還沒有啥收益,因為我們更多地是做離線分析,並非差那幾秒的性能,所以干脆不要了。

  先來看幾個map類型的數據操作方式:

-- 一個泛型的map, 只要給定的值類型正確,就會得到正確類型的map了
-- map<string,string>, map<string,double>, map<string,int>
map('k', 'v1');
map('k', v1);
map('k', v1);
-- 將字符串轉換為map形式,需要自行定義明確的分隔符
-- 注意,json並不能很好地轉換為map形式
-- 以下結果為: {"\"b\"":"2}","{\"a\"":"\"1\""}
select str_to_map('{"a":"1","b":2}') from dual;
-- 以下結果為: {"a":"","b":"2"}
select str_to_map('a:,b:2') from dual;
-- 以下結果為: {"a":"1","b":"2"}
select map('a','1','b','2') from dual;
    
    接下來,我們來看下數據插入方式:
-- 從加工數據集中寫入全量表
insert into table xxx select k1,k2,k3 from a_xxx;
-- 從加工數據集中覆蓋式寫入全量表
insert overwrite table xxx select * from a_xxx;
insert into table xxx partition(pt='xxx') select k1,k2,k3 from a_xxx;
insert into table xxx partition(pt='xxx') select k1,k2,k3 from a_xxx;

-- 將加工結果集創建一個新表寫入
create table tableName ROW FORMAT delimited fields terminated by ',' stored as textfile  as 
    with a as (select * from t1 where pt='xxx') select a.uid from a

-- 插入一條條單獨的記錄
insert into values (v11, v12, v13), (v22, v22, v23);
-- 另外一種插入單條記錄的方式,從虛表中選擇常量集
insert into table xxx select k1,k2,k3 from dual;

 

3. 數據更新

  update數據與delete數據同sql標准協議,並無二致,但需要hive版本大於 0.14,且需要開啟相應選項才可以。即需要支持hive的事務特性。

-- update數據與delete數據同sql標准協議
UPDATE tablename SET column = value [, column = value ...] [WHERE expression]
DELETE FROM tablename [WHERE expression]

 

4. 創建表操作

  創建表的方式與sql標簽協議一致,只是有些特有類型可以使用,比如 map, struct...

-- 創建數據庫
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
  [COMMENT database_comment]
  [LOCATION hdfs_path]
  [MANAGEDLOCATION hdfs_path]
  [WITH DBPROPERTIES (property_name=property_value, ...)];
-- 刪除數據庫
DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE];
-- 創建表
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name    -- (Note: TEMPORARY available in Hive 0.14.0 and later)
  [(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])]
  [COMMENT table_comment]
  [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
  [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
  [SKEWED BY (col_name, col_name, ...)                  -- (Note: Available in Hive 0.10.0 and later)]
     ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
     [STORED AS DIRECTORIES]
  [
   [ROW FORMAT row_format] 
   [STORED AS file_format]
     | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)]  -- (Note: Available in Hive 0.6.0 and later)
  ]
  [LOCATION hdfs_path]
  [TBLPROPERTIES (property_name=property_value, ...)]   -- (Note: Available in Hive 0.6.0 and later)
  [AS select_statement];   -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
 
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
  LIKE existing_table_or_view_name
  [LOCATION hdfs_path];
 
data_type
  : primitive_type
  | array_type
  | map_type
  | struct_type
  | union_type  -- (Note: Available in Hive 0.7.0 and later)
 
primitive_type
  : TINYINT
  | SMALLINT
  | INT
  | BIGINT
  | BOOLEAN
  | FLOAT
  | DOUBLE
  | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later)
  | STRING
  | BINARY      -- (Note: Available in Hive 0.8.0 and later)
  | TIMESTAMP   -- (Note: Available in Hive 0.8.0 and later)
  | DECIMAL     -- (Note: Available in Hive 0.11.0 and later)
  | DECIMAL(precision, scale)  -- (Note: Available in Hive 0.13.0 and later)
  | DATE        -- (Note: Available in Hive 0.12.0 and later)
  | VARCHAR     -- (Note: Available in Hive 0.12.0 and later)
  | CHAR        -- (Note: Available in Hive 0.13.0 and later)
 
array_type
  : ARRAY < data_type >
 
map_type
  : MAP < primitive_type, data_type >
 
struct_type
  : STRUCT < col_name : data_type [COMMENT col_comment], ...>
 
union_type
   : UNIONTYPE < data_type, data_type, ... >  -- (Note: Available in Hive 0.7.0 and later)
 
row_format
  : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        [NULL DEFINED AS char]   -- (Note: Available in Hive 0.13 and later)
  | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
 
file_format:
  : SEQUENCEFILE
  | TEXTFILE    -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE      -- (Note: Available in Hive 0.6.0 and later)
  | ORC         -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET     -- (Note: Available in Hive 0.13.0 and later)
  | AVRO        -- (Note: Available in Hive 0.14.0 and later)
  | JSONFILE    -- (Note: Available in Hive 4.0.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
 
column_constraint_specification:
  : [ PRIMARY KEY|UNIQUE|NOT NULL|DEFAULT [default_value]|CHECK  [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]
 
default_value:
  : [ LITERAL|CURRENT_USER()|CURRENT_DATE()|CURRENT_TIMESTAMP()|NULL ] 
 
constraint_specification:
  : [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, CONSTRAINT constraint_name FOREIGN KEY (col_name, ...) REFERENCES table_name(col_name, ...) DISABLE NOVALIDATE 
    [, CONSTRAINT constraint_name UNIQUE (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, CONSTRAINT constraint_name CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]

-- 刪除表
DROP TABLE [IF EXISTS] table_name [PURGE]; 
-- 表更名
ALTER TABLE table_name RENAME TO new_table_name;
-- 添加分區
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location'][, PARTITION partition_spec [LOCATION 'location'], ...];
-- 刪除分區
ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec IGNORE PROTECTION;

  本部分內容參考官網: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL

 

5. 總結

  hive中對於數據類型要求還是比較嚴的,實際上大部分的關系型數據庫對類型要求都還是比較嚴的(mysql除外,它幾乎可以使用string型類型插入任意字段)。

  在對數據進行插入操作時,需要注意數據類型,必要時做轉換,如果不能做轉換那么就需要換一種寫法了。不過好在,hive對於簡單類型的判定並不太嚴,比如 '1'與1 是相等的, 1.0 和 '1.0' 也都是可以的。而當我們使用presto進行操作時,則不會被支持,其要求的類型更嚴格。

  總之,針對每種類型的數據庫,都有其特有的要求,我往往都需要為各自做相應的適配。所謂的標准協議,也只能從一定程度上約束大家的行為。但也已經非常不錯了,至少大家是在標准的周圍,擴展特有的能力,以滿足不同的業務場景。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM