天天看點

hive操作執行個體官方文檔中文翻譯建立,顯示,修改,和删除表查詢和插入資料原文連結:https://blog.csdn.net/qi49125/article/details/78007181

建立,顯示,修改,和删除表

建立表

以下例子建立表

page_view

CREATE TABLE page_view(viewTime INT, userid BIGINT,
                page_url STRING, referrer_url STRING,
                ip STRING COMMENT 'IP Address of the User')
COMMENT 'This is the page view table'
PARTITIONED BY(dt STRING, country STRING)
STORED AS SEQUENCEFILE;
           

在這個例子中,表的列被指定相應的類型。備注(Comments)可以基于列級别,也可以是表級别。另外,使用PARTITIONED關鍵詞定義的分區列與資料列是不同的,分區列實際上不存儲資料。當使用這種方式建立表的時候,我們假設資料檔案的内容,字段之間以ASCII 001(ctrl-A)分隔,行之間以換行分隔。

如果資料不是以上述格式組織的,我們也可以指定分隔符,如下:

CREATE TABLE page_view(viewTime INT, userid BIGINT,
                page_url STRING, referrer_url STRING,
                ip STRING COMMENT 'IP Address of the User')
COMMENT 'This is the page view table'
PARTITIONED BY(dt STRING, country STRING)
ROW FORMAT DELIMITED
        FIELDS TERMINATED BY '1'
STORED AS SEQUENCEFILE;
           

目前,行分隔符不能指定,因為它不是由Hive決定,而是由Hadoop分隔符。

對表的指定列進行分桶,是一個好的方法,它可以有效地對資料集進行抽樣查詢。如果沒有分桶,則會進行随機抽樣,由于在查詢的時候,需要掃描所有資料,是以,效率不高。以下例子描述了,在表page_view的userid列上進行分桶的例子:

CREATE TABLE page_view(viewTime INT, userid BIGINT,
                page_url STRING, referrer_url STRING,
                ip STRING COMMENT 'IP Address of the User')
COMMENT 'This is the page view table'
PARTITIONED BY(dt STRING, country STRING)
CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS
ROW FORMAT DELIMITED
        FIELDS TERMINATED BY '1'
        COLLECTION ITEMS TERMINATED BY '2'
        MAP KEYS TERMINATED BY '3'
STORED AS SEQUENCEFILE;
           

以上例子,通過一個

userid

的哈希函數,表被分成32個桶。在每個桶中的資料,是以

viewTime

升序進行存儲。這樣組織資料允許使用者有效地在這n個桶上進行抽樣。合适的排序使得内部操作充分利用熟悉的資料結構來進行更加有效的查詢。

CREATE TABLE page_view(viewTime INT, userid BIGINT,
                page_url STRING, referrer_url STRING,
                friends ARRAY<BIGINT>, properties MAP<STRING, STRING>,
                ip STRING COMMENT 'IP Address of the User')
COMMENT 'This is the page view table'
PARTITIONED BY(dt STRING, country STRING)
CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS
ROW FORMAT DELIMITED
        FIELDS TERMINATED BY '1'
        COLLECTION ITEMS TERMINATED BY '2'
        MAP KEYS TERMINATED BY '3'
STORED AS SEQUENCEFILE;
           

在這個例子,CLUSTERED BY指定列進行分桶,以及建立多少個桶。行格式分隔符指定在hive表中,行如何存儲。在這種分隔符情況下,指定了字段是如何結束,集合項(數組和map)如何結束,以及map的key是如何結束的。STORED AS SEQUENCEFILE表示這個資料是以二進制格式進行存儲資料在hdfs上。對于以上例子的ROW FORMAT的值和STORED AS表示系統預設值。

表名和列名不區分大小寫

資料表列資訊檢視

浏覽表和分區
SHOW TABLES;

列出資料庫裡的所有的表,也可以這麼浏覽:

SHOW TABLES 'page.*';

這樣将會列出以page開頭的表,模式遵循Java正規表達式文法。

SHOW PARTITIONS page_view;

列出表的分區。如果表沒有分區,則抛出錯誤。

DESCRIBE page_view;

列出表的列和列的類型。

DESCRIBE EXTENDED page_view;

列出表的列和表的其他屬性。這會列印很多資訊,且輸出的風格不是很友好,通常用于調試。

DESCRIBE EXTENDED page_view PARTITION (ds='2016-08-08');

列出列和分區的所有屬性。這也會列印出許多資訊,通常也是用于調試。
           

修改表

對已有的表進行重命名。如果表的新名字存在,則報錯:

ALTER TABLE old_table_name RENAME TO new_table_name;

對已有表的列名進行重命名。要確定使用相同的列類型,且要包含對每個已存在列的一個入口(也就是說,就算不修改其他列的列名,也要把此列另上,否則,此列會丢失)。

ALTER TABLE old_table_name REPLACE COLUMNS (col1 TYPE, ...);

對已有表增加列:

ALTER TABLE tab1 ADD COLUMNS (c1 INT COMMENT 'a new int column', c2 STRING DEFAULT 'def val');

注意: 
模式的改變(例如增加列),保留了表的老分區,以免它是一個分區表。所有對這些列或老分區的查詢都會隐式地傳回一個null值或這些列指定的預設值。
           

删除表和分區

删除表是相當,表的删除會删除已經建立在表上的任意索引。相關指令是:

DROP TABLE pv_users;

要删除分區。修改表删除分區:

ALTER TABLE pv_users DROP PARTITION (ds='2016-08-08')
           

注意:此表或分區的任意資料都将被删除,而且可能無法恢複。

加載資料

要加載資料到Hive表有許多種方式。使用者可以建立一個“外部表”來指向一個特定的HDFS路徑。用這種方法,使用者可以使用HDFSput或copy指令,複制一個檔案到指定的位置,并且附上相應的行格式資訊建立一個表指定這個位置。一旦完成,使用者就可以轉換資料和插入他們到任意其他的Hive表中。例如,如果檔案/tmp/pv_2016-06-08.txt包含逗号分隔的頁面通路記錄。這需要以合适的分區加載到表page_view,以下指令可以完成這個目标:

CREATE EXTERNAL TABLE page_view_stg(viewTime INT, userid BIGINT,
                page_url STRING, referrer_url STRING,
                ip STRING COMMENT 'IP Address of the User',
                country STRING COMMENT 'country of origination')
COMMENT 'This is the staging page view table'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '44' LINES TERMINATED BY '12'
STORED AS TEXTFILE
LOCATION '/user/data/staging/page_view';
 
hadoop dfs -put /tmp/pv_2016-06-08.txt /user/data/staging/page_view
 
FROM page_view_stg pvs
INSERT OVERWRITE TABLE page_view PARTITION(dt='2016-06-08', country='US')
SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip
WHERE pvs.country = 'US';
           

其中,‘44’是逗号的ASCII碼,‘12’是換頁符(NP from feed,new page)。null是作為目标表中的數組和map類型插入,如果指定了合适的行格式,這些值也可以來自外部表。

如果在HDFS上有一些曆史資料,使用者想增加一些中繼資料,以便于可以使用Hive來查詢和操縱這些資料,這個方法是很有用的。

另外,系統也支援直接從本地檔案系統上加載資料到Hive表。表的格式與輸入檔案的格式需要相同。如果檔案/tmp/pv_2016-06-08包含了US資料,然後我們不需要像前面例子那樣的任何篩選,這種情況的加載可以使用以下文法完成:

LOAD DATA LOCAL INPATH /tmp/pv_2016-06-08_us.txt INTO TABLE page_view PARTITION(date='2016-06-08', country='US')

           

路徑參數可以是一個目錄(這種情況下,目錄下的所有檔案将被加載),一個檔案,或一個通配符(這種情況下,所有比對的檔案會上傳)。如果參數是目錄,它不能包含子目錄。同樣,通配符隻比對檔案名。

在輸入檔案/tmp/pv_2016-06-08.txt非常大的情況下,使用者可以采用并行加載資料的方式(使用Hive的外部工具)。隻要檔案在HDFS上-以下文法可以用于加載資料到Hive表:

LOAD DATA INPATH '/user/data/pv_2016-06-08_us.txt' INTO TABLE page_view PARTITION(date='2016-06-08', country='US')
           

查詢和插入資料

Simple Query

Partition Based Query

Joins

Aggregations

Multi Table/File Inserts

Dynamic-Partition Insert

Inserting into Local Files

Sampling

Union All

Array Operations

Map (Associative Arrays) Operations

Custom Map/Reduce Scripts

Co-Groups

Hive查詢操作在文檔Select,插入操作在文檔insert data into Hive Tables from queries和writing data into the filesystem from queries。

簡單的查詢

對于所有的活躍使用者,可以使用以下查詢格式:

INSERT OVERWRITE TABLE user_active
SELECT user.*
FROM user
WHERE user.active = 1;
           

注意:不像SQL,我們老是插入結果到表中。随後我們會描述,使用者如何檢查這些結果,甚至把結果導出到一個本地檔案。你也可以在Beeline或HiveCLI執行以下查詢:

SELECT user.*
FROM user
WHERE user.active = 1;
           

這在内部将會重寫到一些臨時檔案,并在Hive用戶端顯示。

聚合

統計使用者每個性别的人數,可以使用以下查詢:
INSERT OVERWRITE TABLE pv_gender_sum
SELECT pv_users.gender, count (DISTINCT pv_users.userid)
FROM pv_users
GROUP BY pv_users.gender;

可以同時做多個聚合,然而,兩個聚合函數不能同時用DISTINCT作用于不同的列,以下情況是可以的(DISTINCT作用于相同列):

INSERT OVERWRITE TABLE pv_gender_agg
SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(*), sum(DISTINCT pv_users.userid)
FROM pv_users
GROUP BY pv_users.gender;

然而,以下情況(DISTINCT作用于不同的列)是不允許的:

INSERT OVERWRITE TABLE pv_gender_agg
SELECT pv_users.gender, count(DISTINCT pv_users.userid), count(DISTINCT pv_users.ip)
FROM pv_users
GROUP BY pv_users.gender;
           

多表/檔案插入

聚合或簡單查詢的輸出可以插入到多個表中,或者甚至是HDFS檔案(能夠使用HDFS工具進行操縱)。例如,如果沿用前面的“性别分類”,例子如下:

FROM pv_users
INSERT OVERWRITE TABLE pv_gender_sum
    SELECT pv_users.gender, count_distinct(pv_users.userid)
    GROUP BY pv_users.gender
 
INSERT OVERWRITE DIRECTORY '/user/data/tmp/pv_age_sum'
    SELECT pv_users.age, count_distinct(pv_users.userid)
    GROUP BY pv_users.age;
           

第一個插入語句将結果插入到Hive表中,而第二個插入語句是将結果寫到HDFS檔案。

動太分區插入

在前面的例子中,我們知道,在插入語句中,隻能有一個分區。如果我們想加載到多個分區,我們必須像以下描述來使用多條插入語句:

FROM page_view_stg pvs
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='US')
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'US'
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='CA')
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'CA'
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='UK')
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'UK';
           

為了加載資料到全部的country分區到指定的日期。我們必須在輸入資料中為每個country增加一條插入語句。這是非常不友善的,因為我們需要提前建立且知道已存在哪些country分區清單。如果哪天這些country清單變了,我們必須修改我們的插入語句,也應該建立相應的分區。這也是非常低效的,因為每個插入語句可能都是轉換成一個MapReduce作業。

動态分區插入(Dynamic-partition insert)(或multi-partition插入)就是為了解決以上問題而設計的,它通過動态地決定在掃描資料的時候,哪些分區應該建立和填充。這個新的特征是在版本0.6.0加入的。在動态分區插入中,輸入列被評估,這行應該插入到哪個分區。如果分區沒有建立,它将自動建立這個分區。使用這個特征,我們僅僅需要插入語桀犬吠堯來建立和填充所有需要的分區。另外,因為隻有一個插入語句,相應的也隻有一個MapReduce作業。相比多個插入語句的情況,這将顯著地提高性能且降低Hadoop叢集負載。

以下是使用一個插入語句,加載資料到所有country分區的例子:

FROM page_view_stg pvs
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country)
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip, pvs.country
           

與多條插入語句相比,動态分區插入有一些文法上的不同: 

- country出現在PARTITION後面,但是沒有具體的值。這種情況,country就是一個動态分區列。另一方面,dt有一個值,這意味着它是一個靜态的分區列。如果一個列是動态分區列,它的值将會使用輸入列的值。目前,我們僅僅允許在分區條件的最後一列放置動态分區列,因為分區列的順序,訓示了它的層級次序(意味着dt是根分區,country是子分區)。我們不能這樣指定分區(dt,country=’US’),因為這表示,我們需要更新所有的日期的分區且它的country子分區是‘US’。

一個額外的pvs.country列被加入在查詢語句中。這對動态分區列來說,相當于輸入列。注意:對于靜态分區列,我們不需要添加一個輸入列,因為在PARTITION語句中,它的值已經知道。注意:動态分區列的值(不是名字)查出來是有序的,且是放在select語句的最後。

動态分區插入的語義: 

 對于動态分區列,當已經此分區時,(例如,country='CA'已存在dt根分區下面)如果動态分區插入與輸入資料中相同的值(’CA’),它将會被重寫(overwritten)。

插入到本地檔案

在某些場合,我們需要把輸出寫到一個本地檔案,以便于能用excel表格打開。這可以使用以下指令:

INSERT OVERWRITE LOCAL DIRECTORY '/tmp/pv_gender_sum'
SELECT pv_gender_sum.*
FROM pv_gender_sum;
           

抽樣

抽樣語句允許使用者對資料抽樣查詢,而不是全表查詢。目前,抽樣是對那些在CREATE TABLE語句的CLUSTERED BY修飾的列上。以下例子,我們從表pv_gender_sum表中的32個桶中,選擇第3個桶。

INSERT OVERWRITE TABLE pv_gender_sum_sample
SELECT pv_gender_sum.*
FROM pv_gender_sum TABLESAMPLE(BUCKET 3 OUT OF 32);
           

通常,TABLESAMPLE的文法像這樣:

TABLESAMPLE(BUCKET x OUT OF y)

這個y必須是桶的數量的因子或倍數,桶的數量是在建立表的時候指定的。抽樣所選的桶由桶大小,y和x共同決定。如果y和桶大小相等,則抽樣所選的桶是x對y的求模結果。

TABLESAMPLE(BUCKET 3 OUT OF 16)
           

這将抽樣第3個和第19個桶。桶的編号從0開始。

tablesample語句的另一方面:

TABLESAMPLE(BUCKET 3 OUT OF 64 ON userid)
           

這将抽取第3個桶的一半。

union all

這個語言也支援union all,如果假設我們有兩個不同的表,分别用來記錄使用者釋出的視訊和使用者釋出的評論,以下例子是一個union all 的結果與使用者表再連接配接的查詢:

INSERT OVERWRITE TABLE actions_users
SELECT u.id, actions.date
FROM (
    SELECT av.uid AS uid
    FROM action_video av
    WHERE av.date = '2008-06-03'
 
    UNION ALL
 
    SELECT ac.uid AS uid
    FROM action_comment ac
    WHERE ac.date = '2008-06-03'
    ) actions JOIN users u ON(u.id = actions.uid);
           

數組操作

表的數組列可以這樣:

CREATE TABLE array_table (int_array_column ARRAY<INT>);
           

假設pv.friends 是類型ARRAY<INT>(也就是一個整型數組),使用者可以通過索引号擷取數組中特定的元素,如下:

SELECT pv.friends[2]
FROM page_views pv;
           

這個查詢得到的是pv.friends裡的第三個元素。

使用者也可以使用函數size來擷取數組的長度,如下:

SELECT pv.userid, size(pv.friends)
FROM page_view pv;
           

Map(關聯數組)操作

Map提供了類似于關聯數組的集合。這樣的結構不僅可以由程式建立。我們也将很快可以繼承這個。假設pv.properties是類型map<String,String>,如下:

INSERT OVERWRITE page_views_map
SELECT pv.userid, pv.properties['page type']
FROM page_views pv;
           

這将查詢表page_views的‘page_type‘屬性。

與數組相似,也可以使用函數size來擷取map的大小:

SELECT size(pv.properties)
FROM page_view pv;
           

定制Map/Reduce腳本

通過使用Hive語言原生支援的特征,使用者可以插入他們自己定制的mapper和reducer在資料流中。例如,要運作一個定制的mapper腳本script-map_script和reducer腳本script-reduce_script),使用者可以執行以下指令,使用TRANSFORM來嵌入mapper和reducer腳本。

注意:在執行使用者腳本之前,表的列會轉換成字元串,且由TAB分隔,使用者腳本的标準輸出将會被作為以TAB分隔的字元串列。使用者腳本可以輸出調試資訊到标準錯誤輸出,這個資訊也将顯示hadoop的詳細任務頁面上。

FROM (
     FROM pv_users
     MAP pv_users.userid, pv_users.date
     USING 'map_script'
     AS dt, uid
     CLUSTER BY dt) map_output
 
 INSERT OVERWRITE TABLE pv_users_reduced
     REDUCE map_output.dt, map_output.uid
     USING 'reduce_script'
     AS date, count;
           

map腳本樣本(weekday_mapper.py)

import sys
import datetime
 
for line in sys.stdin:
  line = line.strip()
  userid, unixtime = line.split('\t')
  weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
  print ','.join([userid, str(weekday)])
           

當然,對于那些常見的select轉換,MAP和REDUCE都是“文法糖”。内部查詢也可以寫成這樣:

SELECT TRANSFORM(pv_users.userid, pv_users.date) USING 'map_script' AS dt, uid CLUSTER BY dt FROM pv_users;
           

Co-Groups

在使用map/reduce的群體中,cogroup是相當常見的操作,它是将來自多個表的資料發送到一個定制的reducer,使得行由表的指定列的值進行分組。在Hive的查詢語言中,可以使用以下方式,通過使用union all和cluster by來實作此功能。假設我們想對來自表actions_video和action_comment的行對uid列進行分組,且需要發送他們到reducer_script定制的reducer,可以使用以下文法:

FROM (
     FROM (
             FROM action_video av
             SELECT av.uid AS uid, av.id AS id, av.date AS date
 
            UNION ALL
 
             FROM action_comment ac
             SELECT ac.uid AS uid, ac.id AS id, ac.date AS date
     ) union_actions
     SELECT union_actions.uid, union_actions.id, union_actions.date
     CLUSTER BY union_actions.uid) map
 
 INSERT OVERWRITE TABLE actions_reduced
     SELECT TRANSFORM(map.uid, map.id, map.date) USING 'reduce_script' AS (uid, id, reduced_val);
           

原文連結:https://blog.csdn.net/qi49125/article/details/78007181